Skip to content
This repository was archived by the owner on Jan 4, 2024. It is now read-only.

Commit 7a929a1

Browse files
committed
Merge remote-tracking branch 'upstream/master'
* upstream/master: Basic Auth Configuration (heroku#45) # Conflicts: # scripts/config/templates/nginx.conf.erb
2 parents 3223cc2 + bde9522 commit 7a929a1

File tree

9 files changed

+83
-0
lines changed

9 files changed

+83
-0
lines changed

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,20 @@ You can redirect all HTTP requests to HTTPS.
150150
}
151151
```
152152

153+
#### Basic Authentication
154+
155+
You can enable Basic Authentication so all requests require authentication.
156+
157+
```
158+
{
159+
"basic_auth": true
160+
}
161+
```
162+
163+
This will generate `.htpasswd` using environment variables `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` if they are present. Otherwise it will use a standard `.htpasswd` file present in the `app` directory.
164+
165+
Passwords set via `BASIC_AUTH_PASSWORD` can be generated using OpenSSL or Apache Utils. For instance: `openssl passwd -apr1`.
166+
153167
#### Proxy Backends
154168
For single page web applications like Ember, it's common to back the application with another app that's hosted on Heroku. The down side of separating out these two applications is that now you have to deal with CORS. To get around this (but at the cost of some latency) you can have the static buildpack proxy apps to your backend at a mountpoint. For instance, we can have all the api requests live at `/api/` which actually are just requests to our API server.
155169

scripts/boot

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ esac
1717

1818
"${HERE}/config/make-config"
1919

20+
# Create .htpasswd if BASIC_AUTH_USERNAME and BASIC_AUTH_PASSWORD are provided
21+
"${HERE}/config/make-htpasswd"
22+
2023
# make a shared pipe; we'll write the name of the process that exits to it once
2124
# that happens, and wait for that event below this particular call works on
2225
# Linux and Mac OS (will create a literal ".XXXXXX" on Mac, but that doesn't

scripts/config/lib/nginx_config.rb

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class NginxConfig
88
encoding: "UTF-8",
99
clean_urls: false,
1010
https_only: false,
11+
basic_auth: false,
12+
basic_auth_htpasswd_path: "/app/.htpasswd",
1113
worker_connections: 512,
1214
index: false,
1315
server_name: false,
@@ -51,6 +53,10 @@ def initialize(json_file)
5153
json["index"] ||= DEFAULT[:index]
5254
json["keepalive_timeout"] ||= DEFAULT[:keepalive_timeout]
5355

56+
json["basic_auth"] = true unless ENV['BASIC_AUTH_USERNAME'].nil?
57+
json["basic_auth"] ||= DEFAULT[:basic_auth]
58+
json["basic_auth_htpasswd_path"] ||= DEFAULT[:basic_auth_htpasswd_path]
59+
5460
json["routes"] ||= {}
5561
json["routes"] = NginxConfigUtil.parse_routes(json["routes"])
5662

scripts/config/make-htpasswd

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'json'
4+
5+
USER_CONFIG = "/app/static.json"
6+
7+
config = {}
8+
config = JSON.parse(File.read(USER_CONFIG)) if File.exist?(USER_CONFIG)
9+
10+
HTPASSWD = config["basic_auth_htpasswd_path"] || '/app/.htpasswd'
11+
USERNAME = ENV["BASIC_AUTH_USERNAME"]
12+
PASSWORD = ENV["BASIC_AUTH_PASSWORD"]
13+
14+
htpasswd = "#{USERNAME}:#{PASSWORD}" unless (USERNAME.nil? || PASSWORD.nil?)
15+
16+
File.open(HTPASSWD, 'a') { |file| file.puts(htpasswd) } if !htpasswd.nil?

scripts/config/templates/nginx.conf.erb

+5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ http {
8282
index <%= index %>;
8383
<% end %>
8484

85+
<% if basic_auth %>
86+
auth_basic "Restricted";
87+
auth_basic_user_file <%= basic_auth_htpasswd_path %>;
88+
<% end %>
89+
8590
location / {
8691
mruby_post_read_handler /app/bin/config/lib/ngx_mruby/headers.rb cache;
8792
mruby_set $fallback /app/bin/config/lib/ngx_mruby/routes_fallback.rb cache;

spec/fixtures/basic_auth/.htpasswd

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test:$apr1$Dnavu2z9$ZFxQn/mXVQoeYGD.tA2bW/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foobar

spec/fixtures/basic_auth/static.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"basic_auth": true
3+
}

spec/simple_spec.rb

+34
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,40 @@
182182
end
183183
end
184184

185+
describe "basic_auth" do
186+
context "static.json without basic_auth key" do
187+
let(:name) { "hello_world" }
188+
189+
let(:env) {
190+
{
191+
"BASIC_AUTH_USERNAME" => "test",
192+
"BASIC_AUTH_PASSWORD" => "$apr1$Dnavu2z9$ZFxQn/mXVQoeYGD.tA2bW/"
193+
}
194+
}
195+
196+
it "should require authentication" do
197+
response = app.get("/index.html")
198+
expect(response.code).to eq("401")
199+
end
200+
end
201+
202+
context "static.json with basic_auth key and .htpasswd" do
203+
let(:name) { "basic_auth" }
204+
205+
let(:env) {
206+
{
207+
"BASIC_AUTH_USERNAME" => "test",
208+
"BASIC_AUTH_PASSWORD" => "$apr1$/pb2/xQR$cn7UPcTOLymIH1ZMe.NfO."
209+
}
210+
}
211+
212+
it "should require authentication" do
213+
response = app.get("/foo.html")
214+
expect(response.code).to eq("401")
215+
end
216+
end
217+
end
218+
185219
describe "custom error pages" do
186220
let(:name) { "custom_error_pages" }
187221

0 commit comments

Comments
 (0)