Compare commits
No commits in common. 'docs' and 'secret' have entirely different histories.
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
Version 458.835.16.92, May 2018 |
||||
|
||||
Copyright (C) 2018 Charles Reid <charles@charlesreid1.com> |
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified |
||||
copies of this license document, and changing it is allowed as long |
||||
as the name is changed. |
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO. |
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
# github-heroku-attack-rabbits |
||||
|
||||
## What's this business all about, then? |
||||
|
||||
This repository helps you protect your secret pages by (deep breath): |
||||
|
||||
hosting your secret page of static and/or dynamic content using a free Heroku app |
||||
running a Python Flask server that uses Flask-Dance to authenticate visitors |
||||
with Github which allows you fine-grained access control over your pages based on |
||||
user attributes like organization or team membership or even things like how many |
||||
repositories a user has or how many vowels are in their username. |
||||
|
||||
Also, did I mention the attack rabbits? |
||||
|
||||
![warning: attack rabbits ahead](docs/img/warning.png) |
||||
|
||||
|
||||
## Where is everything? |
||||
|
||||
Final pages: |
||||
|
||||
* The finished product (pages on Heroku protected by attack rabbits) |
||||
is at [github-heroku-attack-rabbits.herokuapp.com](https://github-heroku-attack-rabbits.herokuapp.com) |
||||
|
||||
* The documentation is at [pages.charlesreid1.com/github-heroku-attack-rabbits](https://pages.charlesreid1.com/github-heroku-attack-rabbits) |
||||
|
||||
Two branches in this repo compose the github-heroku-attack-rabbits documentation: |
||||
|
||||
* (**YOU ARE HERE**) The [docs](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/docs) branch |
||||
contains the files needed to generate the |
||||
[github-heroku-attack-rabbits documentation site](https://pages.charlesreid1.com/github-heroku-attack-rabbits). |
||||
|
||||
* The [gh-pages](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/gh-pages) branch |
||||
contains the static files generated from the documentation. |
||||
The contents of this branch compose the |
||||
[github-heroku-attack-rabbits documentation site](https://pages.charlesreid1.com/github-heroku-attack-rabbits). |
||||
|
||||
Two branches illustrate github-heroku-attack-rabbits in practice: |
||||
|
||||
* The [secret](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/secret) branch contains the files needed to create the secret page. |
||||
This repository is public, so obviously these aren't *actually* secret, |
||||
but in practice this would be in a protected repository. |
||||
|
||||
* The [heroku-pages](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/heroku-pages) branch |
||||
contains the content that is actually pushed to Heroku - that is, |
||||
the final Flask app. |
||||
|
||||
|
||||
## Where do I start? |
||||
|
||||
See the [documentation](https://pages.charlesreid1.com/github-heroku-attack-rabbits) |
||||
or [docs/index.md](docs/index.md). |
||||
|
||||
|
||||
## License |
||||
|
||||
This is released under the [WTFPL](LICENSE). |
||||
|
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
# github-heroku-attack-rabbits: secret branch |
||||
|
||||
The secret branch contains the mkdocs source files |
||||
needed to generate the final static content for the |
||||
secret site. |
||||
|
||||
The `secret` branch contains the source files, |
||||
the `heroku-pages` branch contains the finished product. |
||||
|
||||
The `heroku-pages` branch contains the site that is |
||||
actually deployed to Heroku at the Github-Heroku attack |
||||
sheep app: |
||||
|
||||
* [https://github-heroku-attack-rabbits.herokuapp.com](https://github-heroku-attack-rabbits.herokuapp.com). |
||||
|
||||
Lost? Visit the [docs](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits) branch. |
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
body { |
||||
background-color: #efefef; |
||||
} |
||||
div.body { |
||||
background-color: #efefef; |
||||
} |
||||
.md-typeset pre { |
||||
background-color: #ccc; |
||||
} |
||||
|
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
# Custom Domains |
||||
|
||||
If you want to use a custom domain: |
||||
|
||||
* Set up custom domain using Heroku command line interface |
||||
* This will set up a DNS subdomain specifically for your app |
||||
* Point your DNS records to the Heroku DNS subdomain |
||||
|
||||
This also introduces complications with HTTP vs HTTPS: |
||||
OAuth must happen over HTTPS (required by protocol). |
||||
But you the user can control your domain and create |
||||
SSL certificates for it, but Heroku is hosting the app. |
||||
|
||||
You have two options: the free option, and the pay option. |
||||
|
||||
**The pay option:** For $7/mo you can upgrade to hobby nodes, |
||||
which allows you to give Heroku permission to create an SSL |
||||
certificate for your domain. This is the easiest solution |
||||
and requires zero setup, zero certificate management. |
||||
|
||||
**The free option:** You can have your domain (HTTP only) |
||||
forward to Heroku (HTTPS can't be forwarded - that's ***key***). |
||||
When you hit the Heroku domain, it will log the user in to Github. |
||||
When the user logs in successfully, Github will redirect them to |
||||
the callback URL. This callback URL ***MUST*** be HTTPS, so it cannot |
||||
redirect back to your (HTTP-only) custom domain. |
||||
|
||||
That means the userr will, after authenticating with Github, |
||||
always be redirected to `https://my-cool-app.herokuapp.com` |
||||
and never `http://my-cool-custom-domain-that-cannot-be-used-as-a-callback-because-it-is-https-only.com`. |
||||
|
||||
The paid option is much, much simpler in the end |
||||
and will save you $7/mo in setup time alone. |
@ -1,174 +0,0 @@
@@ -1,174 +0,0 @@
|
||||
# Create a Flask App using Flask-Dance |
||||
|
||||
This is the heart of the method. |
||||
|
||||
The best thing to do here is just to walk you through the script. |
||||
|
||||
Import statements: |
||||
|
||||
``` |
||||
import os, json |
||||
from os.path import join, isfile, isdir |
||||
from werkzeug.contrib.fixers import ProxyFix |
||||
from flask import Flask, redirect, url_for, send_from_directory |
||||
from flask_dance.contrib.github import make_github_blueprint, github |
||||
``` |
||||
|
||||
Note that flask-dance adds an OAuth login/callback route |
||||
to your Flask app by creating a `/login` blueprint, |
||||
meaning all the OAuth stuff is just magically available |
||||
via `/login`. |
||||
|
||||
Set paths for static content: |
||||
|
||||
``` |
||||
PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__)) |
||||
STATIC_PATH = 'content' |
||||
``` |
||||
|
||||
Create and configure app. This requires confidential information |
||||
for the Github application you created, specifically the client |
||||
ID and client secret. These are at the very top of the page when |
||||
you visit your app's settings page. |
||||
|
||||
To find this, after you log in, click your profile photo in the |
||||
upper right > Settings > Developer Settings > OAuth Apps > click the |
||||
name for your OAuth app. |
||||
|
||||
``` |
||||
app = Flask(__name__) |
||||
|
||||
# this worked locally, but not on heroku |
||||
app.wsgi_app = ProxyFix(app.wsgi_app) |
||||
|
||||
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "9502861d41e8729c5cae3225920b1b46") |
||||
|
||||
app.config["RESULT_STATIC_PATH"] = STATIC_PATH #os.path.join(PROJECT_ROOT,STATIC_PATH) |
||||
app.config["GITHUB_OAUTH_CLIENT_ID"] = os.environ.get("GITHUB_OAUTH_CLIENT_ID") |
||||
app.config["GITHUB_OAUTH_CLIENT_SECRET"] = os.environ.get("GITHUB_OAUTH_CLIENT_SECRET") |
||||
``` |
||||
|
||||
Now the magic happens: we use flask-dance to create a blueprint |
||||
that has methods and settings all ready to go for us to do the |
||||
OAuth dance. |
||||
|
||||
`make_github_blueprint()` is part of the contrib module of flask-dance. |
||||
There are several similar methods to generate blueprints for |
||||
authenticating with other APIs. |
||||
|
||||
``` |
||||
github_bp = make_github_blueprint( |
||||
client_id = os.environ.get('GITHUB_OAUTH_CLIENT_ID'), |
||||
client_secret = os.environ.get('GITHUB_OAUTH_CLIENT_SECRET'), |
||||
scope='read:org') |
||||
|
||||
app.register_blueprint(github_bp, url_prefix="/login") |
||||
|
||||
contents404 = "<html><body><h1>Status: Error 404 Page Not Found</h1></body></html>" |
||||
contents403 = "<html><body><h1>Status: Error 403 Access Denied</h1></body></html>" |
||||
contents200 = "<html><body><h1>Status: OK 200</h1></body></html>" |
||||
``` |
||||
|
||||
Deal with the `/` route first: |
||||
|
||||
* Check if authorized, if not, redirect them to the login URL |
||||
(magical URLs taken care of magically by our `make_github_blueprint` |
||||
function above) |
||||
* If user is authorized (i.e., if they have gone through the OAuth |
||||
process and given their passsword to Github and been redirected |
||||
to your app with an OAuth token), then the next step is to |
||||
find out some information about them. |
||||
* Use the `github` object to call the Github API directly. |
||||
* Decide what to do from there. |
||||
|
||||
``` |
||||
@app.route('/') |
||||
def index(): |
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
resp = github.get("/user/orgs") |
||||
if resp.ok: |
||||
|
||||
all_orgs = resp.json() |
||||
for org in all_orgs: |
||||
if org['login']=='rainbow-mind-machine': |
||||
``` |
||||
|
||||
The next line is important to how the server works: |
||||
if all of the criteria above have been met, we return |
||||
a static file: |
||||
|
||||
``` |
||||
return send_from_directory(STATIC_PATH, 'index.html') |
||||
``` |
||||
|
||||
This is normally "bad practice," and numerous type A people |
||||
on the internet will tell you Flask should not be used for |
||||
serving static files, and that you should use nginx etc., |
||||
but these fail to igonore the following: |
||||
|
||||
* Heroku does not let you run or configure nginx |
||||
* For crying out loud this example is about attack rabbits |
||||
stop taking everything so seriously |
||||
|
||||
Now that we've got that out of the way... |
||||
|
||||
Here's how we serve up static files. This is a total hack, |
||||
but it works. It takes any arbitrary path supplied by the |
||||
user, and attempts to find a corresponding file to serve up |
||||
on disk. |
||||
|
||||
If the user passes a file, then that file is served up. |
||||
|
||||
If the user passes a directory, then `index.html` is served up. |
||||
|
||||
If the user asks for a non-existent file, a 404 error is shown. |
||||
|
||||
If the user is not allowed to view the content, they will face |
||||
the bowel-emptying terrors of the 403 error. |
||||
|
||||
``` |
||||
@app.route('/<path:path>') |
||||
def catch_all(path): |
||||
|
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
username = github.get("/user").json()['login'] |
||||
|
||||
rsp = app.config["RESULT_STATIC_PATH"] |
||||
resp = github.get("/user/orgs") |
||||
if resp.ok: |
||||
|
||||
all_orgs = resp.json() |
||||
for org in all_orgs: |
||||
if org['login']=='dcppc': |
||||
|
||||
if(path==''): |
||||
return send_from_directory(rsp, 'index.html') |
||||
|
||||
elif(isdir(join(rsp,path))): |
||||
return send_from_directory(join(rsp,path),'index.html') |
||||
|
||||
elif(isfile(join(rsp,path))): |
||||
return send_from_directory(rsp, path) |
||||
|
||||
else: |
||||
return contents404 |
||||
|
||||
return contents403 |
||||
``` |
||||
|
||||
Last, set a default 404 handler, and run the app: |
||||
|
||||
``` |
||||
@app.errorhandler(404) |
||||
def oops(e): |
||||
return contents404 |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
app.run() |
||||
``` |
||||
|
@ -1,25 +0,0 @@
@@ -1,25 +0,0 @@
|
||||
# Authenticate Users on Github Membership |
||||
|
||||
For the sake of simplicity, will just demonstrate how this |
||||
works for a single route, but you can combine different |
||||
rules into multiple routes to provide access to different |
||||
people on different parts of a site. |
||||
|
||||
Here is the relevant method that serves up `index.html` |
||||
if the user is authenticated: |
||||
|
||||
``` |
||||
@app.route('/') |
||||
def index(): |
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
resp = github.get("/user") |
||||
|
||||
if resp.ok: |
||||
return send_from_directory(STATIC_PATH, 'index.html') |
||||
|
||||
return contents403 |
||||
``` |
||||
|
||||
|
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
# Authenticate Users on Organization or Team Membership |
||||
|
||||
Here is how we can make access to a given page or route |
||||
conditional on membership in an organization (in this |
||||
example, membership in the `rainbow-mind-machine` organization |
||||
is required for access): |
||||
|
||||
``` |
||||
@app.route('/') |
||||
def index(): |
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
resp = github.get("/user/orgs") |
||||
if resp.ok: |
||||
|
||||
all_orgs = resp.json() |
||||
for org in all_orgs: |
||||
if org['login']=='rainbow-mind-machine': |
||||
return send_from_directory(STATIC_PATH, 'index.html') |
||||
``` |
||||
|
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
# Authenticate Users on Other Criteria |
||||
|
||||
Suppose we wanted to do something silly like restrict |
||||
access to a page to users with Github handles that were |
||||
between 5 and 7 letters. |
||||
|
||||
Here is the relevant method that serves up `index.html` |
||||
if the user's Github handle is 5-7 letters long: |
||||
|
||||
``` |
||||
@app.route('/') |
||||
def index(): |
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
resp = github.get("/user") |
||||
|
||||
if resp.ok: |
||||
username = resp.json()['login'] |
||||
if len(username)>=5 and len(username)<=7: |
||||
return send_from_directory(STATIC_PATH, 'index.html') |
||||
|
||||
return contents403 |
||||
``` |
||||
|
||||
|
||||
|
@ -1,64 +0,0 @@
@@ -1,64 +0,0 @@
|
||||
# Authenticate Different Users on Different Portions of Site |
||||
|
||||
**NOTE: if you are authenticating using membership on a team, you will need the |
||||
team id of the team you are interested in authenticating against.** |
||||
|
||||
For this example, let's expand the routes we're looking at |
||||
a bit more. |
||||
|
||||
Suppose we have two folders, `team_only` and `org_only`. |
||||
|
||||
The `team_only` folder should only be accessible to your team, `Team Gold`. |
||||
|
||||
The `org_only` folder should only be accessible to your organization, `Colorful Colors`. |
||||
|
||||
The main site (i.e., all other files) should be publicly accessible. |
||||
|
||||
``` |
||||
@app.route('/') |
||||
def index(): |
||||
return send_from_directory(STATIC_PATH, 'index.html') |
||||
|
||||
|
||||
@app.route('/team_only/<path:path>') |
||||
def team_gold(path): |
||||
|
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
rsp = app.config["RESULT_STATIC_PATH"] |
||||
|
||||
resp = github.get("/user") |
||||
if resp.ok: |
||||
username = resp.json()['login'] |
||||
|
||||
team_id = 'XXXXX' |
||||
|
||||
resp = github.get("/teams/%s/members/%s"%( team_id, username )) |
||||
if resp.code==204: |
||||
team_gold_dir = os.path.join(STATIC_PATH, 'team_only') |
||||
return send_from_directory(team_gold_dir, 'index.html') |
||||
return contents403 |
||||
|
||||
|
||||
@app.route('/org_only/<path:path>') |
||||
def team_gold(path): |
||||
|
||||
if not github.authorized: |
||||
return redirect(url_for("github.login")) |
||||
|
||||
rsp = app.config["RESULT_STATIC_PATH"] |
||||
|
||||
resp = github.get("/user") |
||||
if resp.ok: |
||||
|
||||
my_org = 'XXXXXXXX' |
||||
|
||||
all_orgs = resp.json() |
||||
for org in all_orgs: |
||||
if org['login']==my_org: |
||||
color_org_dir = os.path.join(STATIC_PATH, 'org_only') |
||||
return send_from_directory(color_org_dir, 'index.html') |
||||
return contents403 |
||||
``` |
||||
|
@ -1,98 +0,0 @@
@@ -1,98 +0,0 @@
|
||||
# Deploying to Heroku |
||||
|
||||
Once we have debugged the Flask app and we are happy with it, |
||||
we are ready to deploy it to Heroku. |
||||
|
||||
|
||||
## Repository Setup |
||||
|
||||
To do this, you should set up your repo as follows: |
||||
|
||||
Clone the repo: |
||||
|
||||
``` |
||||
$ git clone https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits.git |
||||
``` |
||||
|
||||
The repo has the following structure: |
||||
|
||||
``` |
||||
github-heroku-attack-rabbits/ |
||||
LICENSE |
||||
README.md |
||||
mkdocs.yml |
||||
docs/ |
||||
index.md |
||||
... |
||||
mkdocs-material/ |
||||
... |
||||
``` |
||||
|
||||
Now, inside the repo, clone the repo again, |
||||
but this time clone the `heroku-pages` branch |
||||
to the `site/` directory: |
||||
|
||||
``` |
||||
$ cd github-heroku-attack-rabbits/ |
||||
$ git clone -b heroku-pages https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits.git site |
||||
``` |
||||
|
||||
|
||||
## Heroku Deploy Process |
||||
|
||||
To deploy content to Heroku, we add our Heroku project as a git remote |
||||
(see the [heroku](heroku.md) page for how to do that) and then push to |
||||
to the master branch of the heroku remote git repo. Changes are pulled |
||||
in by Heroku and the app is restarted each time you run `git push`. |
||||
|
||||
We walk through the steps below. |
||||
|
||||
|
||||
## Heroku Login |
||||
|
||||
From the `site/` directory containing the contents of the `heroku-pages` branch, |
||||
that is, containing the Python flask app, log in to Heroku: |
||||
|
||||
``` |
||||
$ heroku login |
||||
``` |
||||
|
||||
|
||||
## Add Heroku Remote to `heroku-pages` Branch |
||||
|
||||
Now have Heroku add the proper git remote address: |
||||
|
||||
``` |
||||
$ heroku git:remote -a <heroku-app-name> |
||||
``` |
||||
|
||||
Now you're ready to deploy to Heroku. |
||||
|
||||
|
||||
## Deploy to Heroku |
||||
|
||||
Double check your app is ready, then deploy: |
||||
|
||||
``` |
||||
$ git push heroku heroku-pages:master |
||||
``` |
||||
|
||||
This will push the local branch `heroku-pages` to |
||||
the remote branch `master` on the `heroku` remote. |
||||
This should begin a pre-commit hook where Heroku |
||||
compiles your Python app. You should get the green |
||||
light, if you tested your app locally and everything |
||||
was good to go. |
||||
|
||||
|
||||
## Check Your Heroku App |
||||
|
||||
Your Heroku app will be available at |
||||
|
||||
``` |
||||
https://<heroku-app-name>.herokuapp.com |
||||
``` |
||||
|
||||
You should see your Python flask app |
||||
show up shortly. |
||||
|
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
# Testing Flask App Locally |
||||
|
||||
We set up the Github App to use a callback of `https://localhost:5000/login/github/authorized` |
||||
so that we could test the app locally. Now it is time to test the app locally. |
||||
|
||||
The application needs access to your Github app id and token. Those are provided |
||||
via the `GITHUB_OAUTH_CLIENT_{ID,SECRET}` environment variables. Set these |
||||
when you run the actual python command to run the server: |
||||
|
||||
``` |
||||
$ GITHUB_OAUTH_CLIENT_ID="xxxxxxx" \ |
||||
GITHUB_OAUTH_CLIENT_SECRET="xxxxxxx" \ |
||||
OAUTHLIB_INSECURE_TRANSPORT=true \ |
||||
python github.py |
||||
``` |
||||
|
||||
This runs the Flask server on port 5000, where it will wait for a visitor. |
||||
The way we have our application written in this example, the main `/` route |
||||
will redirect the user to a Github login screen immediately, but you could |
||||
also present the user with a friendly welcome page when they go to `/`, |
||||
and only redirect them to the Github login prompt when they visit a |
||||
URL like `/login` or `/auth`. |
||||
|
||||
Once you run the above command, open the following URL in your browser: |
||||
|
||||
``` |
||||
http://localhost:5000/ |
||||
``` |
||||
|
||||
**NOTE: Make sure you are logged out of Github and that you clear your cookies |
||||
if you are already logged in as one user and wish to authenticate as another. |
||||
The login is _very_ persistent so you may need to close and re-open your browser.** |
||||
|
||||
Visiting the address above will result in your being redirected to a Github |
||||
login page. Once you login, Github will redirect the user back to the |
||||
github-heroku-attack-rabbits application with a token that the application |
||||
can use to perform actions on behalf of the user. |
||||
|
||||
## Next Step? |
||||
|
||||
If the app works, the next step is to deploy to Heroku. |
||||
|
@ -1,57 +0,0 @@
@@ -1,57 +0,0 @@
|
||||
## get started with github |
||||
|
||||
We mentioned on the [heroku](heroku.md) page that heroku |
||||
creates a remote git repository to hold the files you |
||||
want to host. |
||||
|
||||
To use the contents of a Github repository on Heroku, |
||||
just treat it like another git remote, no special setup |
||||
is needed. |
||||
|
||||
However, to set up your Github-Heroku attack rabbits to |
||||
authenticate a user via Github, and mercilessly attack |
||||
all intruders, you must create a Github OAuth App. |
||||
|
||||
### Creating Github OAuth App |
||||
|
||||
Log into Github |
||||
|
||||
Go to Settings |
||||
|
||||
Click "Developer Settings" on the left side |
||||
|
||||
Click "New OAuth App" button in upper right |
||||
|
||||
**What do these settings mean?** |
||||
|
||||
* **Application name** is what will be shown to users when they visit |
||||
a page protected by the attack rabbits and are prompted for |
||||
their password by Github. |
||||
|
||||
* **Homepage URL/Application description** are for users who want to know more |
||||
about your killer attack rabbit Github app |
||||
|
||||
* **Authorization callback URL** is the URL that the users will be sent to |
||||
once they authenticate with Github and they are granted an OAuth token. |
||||
This is the magic ingredient that allows you to take actions on behalf |
||||
of the account logging in. |
||||
|
||||
In this guide we'll cover the case of checking membership in organizations or teams, |
||||
but what your attack rabbits end up doing to determine if a user is allowed to |
||||
access your secret pages is up to you. |
||||
|
||||
## Values to use |
||||
|
||||
You should set your own values for the **name** and **description** fields. |
||||
|
||||
The **home URL** is not actually necessary - it is simply provided for users to |
||||
get more information about your app. |
||||
|
||||
The most important is the **callback URL**, which should be set to: |
||||
|
||||
http://localhost:5000/login/github/authorized |
||||
|
||||
This is for testing locally *only*. |
||||
|
||||
Don't use HTTPS in the callback URL! |
||||
|
@ -1,67 +0,0 @@
@@ -1,67 +0,0 @@
|
||||
# create heroku app |
||||
|
||||
|
||||
### Heroku toolbelt |
||||
|
||||
Heroku offers a really nice command line interface tool called |
||||
Heroku Toolbelt. It is available through Homebrew and Aptitude: |
||||
|
||||
``` |
||||
$ brew install heroku # from Mac |
||||
|
||||
$ apt-get install heroku # from Ubuntu |
||||
``` |
||||
|
||||
It is then available on the command line as `heroku`. |
||||
|
||||
The first thing you should do is authenticate with |
||||
your Heroku account by running |
||||
|
||||
``` |
||||
$ heroku login |
||||
``` |
||||
|
||||
We will use this command line application for the following tasks: |
||||
|
||||
* Create a git remote to point to the right Heroku git remote location |
||||
* Set environment variables (for e.g. secret keys) on the remote Heroku instance |
||||
* Get information (logs, status, etc.) about your Heroku app |
||||
|
||||
We will cover these commands as they come up. |
||||
|
||||
|
||||
### Create heroku app |
||||
|
||||
Start by creating a heroku app. |
||||
|
||||
* Each heroku app must have a unique name |
||||
* Each heroku app creates a remote git repo |
||||
* Master branch is what Heroku deploys publicly on herokuapps.com |
||||
* You will also need heroku CLI to link your github repo to your heroku app |
||||
|
||||
|
||||
### Where heroku app lives |
||||
|
||||
Suppose you are creating an app called `my-cool-app` |
||||
on heroku. Then your application will be hosted by |
||||
Heroku and will be available at the URL: |
||||
|
||||
``` |
||||
https://my-cool-app.herokuapp.com |
||||
``` |
||||
|
||||
### How heroku apps works |
||||
|
||||
If you have used Github Pages before, Heroku uses a similar |
||||
model (live hosting one particular branch of a git repository). |
||||
However, Heroku is different because you can run dynamic scripts |
||||
using Python, Ruby, PHP, etc. |
||||
|
||||
To change the content of your Heroku app, just change the contents |
||||
of the repository, and push to master (push to the master branch of |
||||
the remote Heroku repository). |
||||
|
||||
You will need to structure your repository carefully. |
||||
That's what this page is here to help you do. |
||||
Heroku can figure out the rest from there. |
||||
|
Before Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 46 KiB |
@ -1,92 +0,0 @@
@@ -1,92 +0,0 @@
|
||||
# github-heroku-attack-rabbits |
||||
|
||||
## What's this business all about, then? |
||||
|
||||
This repository helps you put access control into place to protect your secret pages by (deep breath): |
||||
|
||||
hosting your secret page of static and/or dynamic content by using a free Heroku app |
||||
running a Python Flask server that uses Flask-Dance to authenticate visitors |
||||
with Github using OAuth which allows you fine-grained access control for your pages |
||||
using user attributes like organization or team membership or even things like how many |
||||
vowels a user has in their username. |
||||
|
||||
Also, did I mention the attack rabbits? |
||||
|
||||
![warning: attack rabbits ahead](img/warning.png) |
||||
|
||||
|
||||
## Where is everything? |
||||
|
||||
Final pages: |
||||
|
||||
* The finished product (pages on Heroku protected by attack rabbits) |
||||
is at [github-heroku-attack-rabbits.herokuapp.com](https://github-heroku-attack-rabbits.herokuapp.com) |
||||
|
||||
* The documentation is at [pages.charlesreid1.com/github-heroku-attack-rabbits](https://pages.charlesreid1.com/github-heroku-attack-rabbits) |
||||
|
||||
Two branches in this repo compose the github-heroku-attack-rabbits documentation: |
||||
|
||||
* (**YOU ARE HERE**) The [docs](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/docs) branch |
||||
contains the files needed to generate the |
||||
[github-heroku-attack-rabbits documentation site](https://pages.charlesreid1.com/github-heroku-attack-rabbits). |
||||
|
||||
* The [gh-pages](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/gh-pages) branch |
||||
contains the static files generated from the documentation. |
||||
The contents of this branch compose the |
||||
[github-heroku-attack-rabbits documentation site](https://pages.charlesreid1.com/github-heroku-attack-rabbits). |
||||
|
||||
Two branches illustrate github-heroku-attack-rabbits in practice: |
||||
|
||||
* The [secret](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/secret) branch contains the files needed to create the secret page. |
||||
This repository is public, so obviously these aren't *actually* secret, |
||||
but in practice this would be in a protected repository. |
||||
|
||||
* The [heroku-pages](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/heroku-pages) branch |
||||
contains the content that is actually pushed to Heroku - that is, |
||||
the final Flask app. |
||||
|
||||
|
||||
## Contents |
||||
|
||||
An overview of the steps: |
||||
|
||||
[Get Started with Heroku](heroku.md) |
||||
|
||||
[Get Started with Github](github.md) |
||||
|
||||
[Initialize Repository: Branches](repo.md) |
||||
|
||||
[Create a Flask App using Flask-Dance](flask.md) |
||||
|
||||
* [Authenticate users based on Github membership only](flask_auth_github.md) |
||||
* [Authenticate users based on organization or team membership](flask_auth_org.md) |
||||
* [Authenticate users based on some other criteria](flask_auth_other.md) |
||||
* [Protection portions of the site](flask_auth_portions.md) |
||||
|
||||
[Test Flask App Locally](flask_local.md) |
||||
|
||||
[Deploying Flask App to Heroku](flask_heroku.md) |
||||
|
||||
[Custom Domains](custom_domains.md) |
||||
|
||||
|
||||
## Links |
||||
|
||||
Python software used: |
||||
|
||||
* [Flask](http://flask.pocoo.org/) |
||||
* [Flask-dance](https://github.com/singingwolfboy/flask-dance) |
||||
* [Flask-dance-github](https://github.com/singingwolfboy/flask-dance-github) |
||||
* [mkdocs-material (documentation theme)](https://github.com/squidfunk/mkdocs-material) |
||||
* [mkdocs (documentation)](http://www.mkdocs.org/) |
||||
|
||||
Commercial services: |
||||
|
||||
* [Heroku](https://heroku.com) |
||||
* [Github](https://github.com) |
||||
|
||||
|
||||
## License |
||||
|
||||
This is released under the [WTFPL](https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits/src/branch/docs/LICENSE). |
||||
|
@ -1,110 +0,0 @@
@@ -1,110 +0,0 @@
|
||||
# Initialize Git Repository |
||||
|
||||
Let's talk through how a repository should be laid out |
||||
if we're going to be hosting a Flask app on Heroku. |
||||
|
||||
## Branches |
||||
|
||||
We will need a minimum of two branches. Here we specify |
||||
the names that these branches will have in your Github repo, |
||||
**which is different from the names of the branches on Heroku**: |
||||
|
||||
Branches on Github: |
||||
|
||||
* `heroku-pages` - this branch contains the content that Heroku will host. |
||||
Specifically, it contains the Flask application in a `.py` file, |
||||
and a few other files to help Heroku determine how to run the app |
||||
and what to install. |
||||
|
||||
* `master` - this branch contains the content used to generate the documentation |
||||
and page content that is being hosted behind the Heroku attack sheep. |
||||
The documentation you are reading right now is from the master branch, |
||||
and was made with `mkdocs`. |
||||
|
||||
On Heroku, we only have a single branch: |
||||
|
||||
* `master` (Heroku) maps to `heroku-pages` (Github) |
||||
|
||||
## Repo Layout |
||||
|
||||
Let's talk about the layout of the repository. |
||||
|
||||
If you wish to build the site in order to deploy it to Heroku, |
||||
you should clone the `master` branch (preparing to make the |
||||
content for your attack sheep-protected page): |
||||
|
||||
``` |
||||
$ git clone -b master https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits.git |
||||
$ cd github-heroku-attack-rabbits |
||||
``` |
||||
|
||||
Once you are *inside* the master branch, clone the repo again, |
||||
but this time clone the `heroku-pages` branch, and clone it |
||||
to the `site/` folder: |
||||
|
||||
``` |
||||
$ git clone -b heroku-pages https://git.charlesreid1.com/charlesreid1/github-heroku-attack-rabbits.git site |
||||
$ cd site |
||||
``` |
||||
|
||||
Now you will want to set up the Heroku remote: |
||||
|
||||
``` |
||||
$ heroku git:remote -a my-cool-project |
||||
``` |
||||
|
||||
The layout should now be: |
||||
|
||||
``` |
||||
my-cool-project-repo/ <-- my-cool-project repo pointing to master branch |
||||
|
||||
docs/ \ |
||||
index.md | |
||||
heroku.md | <-- mkdocs files |
||||
... | (can use any static content generator: |
||||
| pelican, sphinx, etc.) |
||||
mkdocs.yml / |
||||
|
||||
site/ <-- my-cool-project repo pointing to heroku-pages branch |
||||
|
||||
Procfile \ |
||||
github.py | <-- heroku python app files |
||||
requirements.txt | (can also use ruby, php, js, etc.) |
||||
runtime.txt | (can also use ruby, php, js, etc.) |
||||
... / |
||||
|
||||
content/ \ |
||||
index.html | <-- static content hosted by Flask |
||||
sitemap.xml | |
||||
... / |
||||
``` |
||||
|
||||
|
||||
## Workflow |
||||
|
||||
Once you have things set up according to the instructions and diagram above, |
||||
you're ready to run the push-to-deploy workflow and start running your secret |
||||
site on Heroku. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
.md-typeset h1 { font-weight: 600; } |
||||
.md-typeset h2 { font-weight: 600; } |
||||
.md-typeset h3 { font-weight: 600; } |
||||
.md-typeset h4 { font-weight: 600; } |
||||
|
||||
body { |
||||
background-color: #f2f9f7; |
||||
} |
||||
div.body { |
||||
background-color: #f2f9f7; |
||||
} |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# The Secret Society of the Fish Slapping Dance |
||||
|
||||
Welcome, and congratulations on having an even number of vowels in your Github handle. |
||||
|
||||
And now for something completely expected: |
||||
|
||||
[Fish-Slapping Dance](https://www.youtube.com/watch?v=T8XeDvKqI4E) |
||||
|
After Width: | Height: | Size: 598 KiB |
After Width: | Height: | Size: 621 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
# Secret Index |
||||
|
||||
This is an index of secret pages. Note that this page is not protected. |
||||
|
||||
You will be asked to authenticate when you click the links below. |
||||
|
||||
If your username has an **even number of vowels**, you are a member |
||||
of the [Secret Society of the Fish Slappers](fishslap.md). |
||||
Click the link to log in and proceed, or else be attacked by |
||||
the Github-Heroku attack rabbits. |
||||
|
||||
If your username has an **odd number of vowels**, you are a member |
||||
of the [Secret Ministerial Department for Theoretical Silly Walk Studies](sillywalk.md). |
||||
Click the link to log in and proceed, or else be attacked by |
||||
the Github-Heroku attack rabbits. |
||||
|
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# The Secret Ministry of Silly Walks |
||||
|
||||
Welcome, and congratulations on having an odd number of vowels in your Github handle. |
||||
|
||||
And now for something completely expected: |
||||
|
||||
|
||||
[Ministry of Sily Walks](https://www.youtube.com/watch?v=IqhlQfXUk7w) |
||||
|