Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MISC] Add coverage for Remote-User and Remote-Groups #982

Merged
merged 6 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions internal/server/public_html.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package server

import "aletheia.icu/broccoli/fs"

// Mock the embedded filesystem for unit tests.
var br = fs.New(false, []byte(""))
// Mock the embedded filesystem for unit tests. The bundle is built from an empty file and
// allows to run the dev workflow without failure.
var br = fs.New(false, []byte("\x1b~\x00\x80\x8d\x94n\xc2|\x84J\xf7\xbfn\xfd\xf7w;.\x8d m\xb2&\xd1Z\xec\xb2\x05\xb9\xc00\x8a\xf7(\x80^78\t(\f\f\xc3p\xc2\xc1\x06[a\xa2\xb3\xa4P\xe5\xa14\xfb\x19\xb2cp\xf6\x90-Z\xb2\x11\xe0l\xa1\x80\\\x95Vh\t\xc5\x06\x16\xfa\x8c\xc0\"!\xa5\xcf\xf7$\x9a\xb2\a`\xc6\x18\xc8~\xce8\r\x16Z\x9d\xc3\xe3\xff\x00"))
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ services:
labels:
# Traefik 1.x
- 'traefik.frontend.rule=Host:login.example.com;PathPrefix:/api'
- 'traefik.protocol=https'
# Traefik 2.x
- 'traefik.http.routers.authelia_backend.rule=Host(`login.example.com`) && PathPrefix(`/api`)'
- 'traefik.http.routers.authelia_backend.entrypoints=https'
Expand Down
1 change: 0 additions & 1 deletion internal/suites/example/compose/haproxy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ apk add --no-cache \
curl \
lua5.3-socket \
openssl && \
curl -Lfs -o /usr/local/etc/haproxy/auth-request.lua "https://raw.githubusercontent.com/TimWolla/haproxy-auth-request/master/auth-request.lua" && \
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=AU/ST=Victoria/L=Melbourne/O=Authelia/CN=*.example.com" -keyout haproxy.key -out haproxy.crt && \
cat haproxy.key haproxy.crt > /usr/local/etc/haproxy/haproxy.pem
103 changes: 103 additions & 0 deletions internal/suites/example/compose/haproxy/auth-request.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
-- The MIT License (MIT)
--
-- Copyright (c) 2018 Tim Düsterhus
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.

local http = require("socket.http")

core.register_action("auth-request", { "http-req" }, function(txn, be, path)
txn:set_var("txn.auth_response_successful", false)

-- Check whether the given backend exists.
if core.backends[be] == nil then
txn:Alert("Unknown auth-request backend '" .. be .. "'")
txn:set_var("txn.auth_response_code", 500)
return
end

-- Check whether the given backend has servers that
-- are not `DOWN`.
local addr = nil
for name, server in pairs(core.backends[be].servers) do
local status = server:get_stats()['status']
if status == "no check" or status:find("UP") == 1 then
addr = server:get_addr()
break
end
end
if addr == nil then
txn:Warning("No servers available for auth-request backend: '" .. be .. "'")
txn:set_var("txn.auth_response_code", 500)
return
end

-- Transform table of request headers from haproxy's to
-- socket.http's format.
local headers = {}
for header, values in pairs(txn.http:req_get_headers()) do
if header ~= 'content-length' then
for i, v in pairs(values) do
if headers[header] == nil then
headers[header] = v
else
headers[header] = headers[header] .. ", " .. v
end
end
end
end

-- Make request to backend.
local b, c, h = http.request {
url = "http://" .. addr .. path,
headers = headers,
create = core.tcp,
-- Disable redirects, because DNS does not work here.
redirect = false,
-- We do not check body, so HEAD
method = "HEAD",
}

-- Check whether we received a valid HTTP response.
if b == nil then
txn:Warning("Failure in auth-request backend '" .. be .. "': " .. c)
txn:set_var("txn.auth_response_code", 500)
return
end

txn:set_var("txn.auth_response_code", c)

-- 2xx: Allow request.
if 200 <= c and c < 300 then
if h["remote-user"] then
txn:set_var("txn.auth_user", h["remote-user"])
end
if h["remote-groups"] then
txn:set_var("txn.auth_groups", h["remote-groups"])
end
txn:set_var("txn.auth_response_successful", true)
-- Don't allow other codes.
-- Codes with Location: Passthrough location at redirect.
elseif c == 301 or c == 302 or c == 303 or c == 307 or c == 308 then
txn:set_var("txn.auth_response_location", h["location"])
-- 401 / 403: Do nothing, everything else: log.
elseif c ~= 401 and c ~= 403 then
txn:Warning("Invalid status code in auth-request backend '" .. be .. "': " .. c)
end
end, 2)
1 change: 1 addition & 0 deletions internal/suites/example/compose/haproxy/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ services:
build: ./example/compose/haproxy/
volumes:
- ./example/compose/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./example/compose/haproxy/auth-request.lua:/usr/local/etc/haproxy/auth-request.lua
networks:
authelianet:
# Set the IP to be able to query on port 8080
Expand Down
13 changes: 12 additions & 1 deletion internal/suites/example/compose/haproxy/haproxy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ frontend fe_http
acl host-authelia-portal hdr(host) -i login.example.com:8080
acl api-path path_beg -i /api
acl protected-frontends hdr(host) -m reg -i ^(admin|home|public|secure|singlefactor)\.example\.com
acl is_headers path -i -m end /headers

http-request set-var(req.scheme) str(https) if { ssl_fc }
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
Expand All @@ -37,9 +38,11 @@ frontend fe_http
# does not know how to handle it (see https://github.com/TimWolla/haproxy-auth-request/issues/12).
http-request lua.auth-request be_auth_request /api/verify if protected-frontends

http-request redirect location https://login.example.com:8080 if protected-frontends !{ var(txn.auth_response_successful) -m bool }

use_backend be_authelia if host-authelia-portal api-path
use_backend fe_authelia if host-authelia-portal !api-path
use_backend be_authelia if protected-frontends !{ var(txn.auth_response_successful) -m bool }
use_backend be_httpbin if protected-frontends is_headers
use_backend be_protected if protected-frontends
use_backend be_mail if { hdr(host) -i mail.example.com:8080 }

Expand All @@ -63,3 +66,11 @@ backend be_mail

backend be_protected
server nginx-backend nginx-backend:80

backend be_httpbin
acl remote_user_exist var(txn.auth_user) -m found
acl remote_groups_exist var(txn.auth_groups) -m found

http-request set-header Remote-User %[var(txn.auth_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(txn.auth_groups)] if remote_groups_exist
server httpbin-backend httpbin:8000
17 changes: 17 additions & 0 deletions internal/suites/example/compose/httpbin/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,20 @@ services:
image: citizenstig/httpbin
networks:
- authelianet
labels:
# Traefik 1.x
- 'traefik.frontend.rule=Host:public.example.com;Path:/headers'
- 'traefik.frontend.priority=120'
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080/'
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true'
- 'traefik.frontend.auth.forward.trustForwardHeader=true'
- 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups'
# Traefik 2.x
- 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)'
- 'traefik.http.routers.httpbin.priority=150'
- 'traefik.http.routers.httpbin.tls=true'
- 'traefik.http.routers.httpbin.middlewares=authelia'
- 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091/api/verify?rd=https://login.example.com:8080/'
- 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true'
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups'
4 changes: 2 additions & 2 deletions internal/suites/example/compose/nginx/portal/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ http {
auth_request /auth_verify;

auth_request_set $user $upstream_http_remote_user;
proxy_set_header Custom-Forwarded-User $user;
proxy_set_header Remote-User $user;

auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Custom-Forwarded-Groups $groups;
proxy_set_header Remote-Groups $groups;

set $target_url $scheme://$http_host$request_uri;
error_page 401 =302 https://login.example.com:8080/?rd=$target_url;
Expand Down
11 changes: 8 additions & 3 deletions internal/suites/scenario_custom_headers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,17 @@ func (s *CustomHeadersScenario) TestShouldNotForwardCustomHeaderForUnauthenticat

body, err := s.WebDriver().FindElement(selenium.ByTagName, "body")
s.Assert().NoError(err)
s.WaitElementTextContains(ctx, s.T(), body, "httpbin:8000")
s.WaitElementTextContains(ctx, s.T(), body, "\"Host\"")

b, err := body.Text()
s.Assert().NoError(err)
s.Assert().NotContains(b, "john")
s.Assert().NotContains(b, "admins")
}

type Headers struct {
ForwardedGroups string `json:"Custom-Forwarded-Groups"`
ForwardedUser string `json:"Custom-Forwarded-User"`
ForwardedGroups string `json:"Remote-Groups"`
ForwardedUser string `json:"Remote-User"`
}

type HeadersPayload struct {
Expand Down
1 change: 1 addition & 0 deletions internal/suites/suite_haproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func init() {
"internal/suites/example/compose/nginx/backend/docker-compose.yml",
"internal/suites/example/compose/haproxy/docker-compose.yml",
"internal/suites/example/compose/smtp/docker-compose.yml",
"internal/suites/example/compose/httpbin/docker-compose.yml",
})

setup := func(suitePath string) error {
Expand Down
4 changes: 4 additions & 0 deletions internal/suites/suite_haproxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (s *HAProxySuite) TestTwoFactorScenario() {
suite.Run(s.T(), NewTwoFactorScenario())
}

func (s *HAProxySuite) TestCustomHeaders() {
suite.Run(s.T(), NewCustomHeadersScenario())
}

func TestHAProxySuite(t *testing.T) {
suite.Run(t, NewHAProxySuite())
}
1 change: 1 addition & 0 deletions internal/suites/suite_traefik.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func init() {
"internal/suites/example/compose/nginx/backend/docker-compose.yml",
"internal/suites/example/compose/traefik/docker-compose.yml",
"internal/suites/example/compose/smtp/docker-compose.yml",
"internal/suites/example/compose/httpbin/docker-compose.yml",
})

setup := func(suitePath string) error {
Expand Down
1 change: 1 addition & 0 deletions internal/suites/suite_traefik2.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func init() {
"internal/suites/example/compose/nginx/backend/docker-compose.yml",
"internal/suites/example/compose/traefik2/docker-compose.yml",
"internal/suites/example/compose/smtp/docker-compose.yml",
"internal/suites/example/compose/httpbin/docker-compose.yml",
})

setup := func(suitePath string) error {
Expand Down
4 changes: 4 additions & 0 deletions internal/suites/suite_traefik2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (s *Traefik2Suite) TestTwoFactorScenario() {
suite.Run(s.T(), NewTwoFactorScenario())
}

func (s *Traefik2Suite) TestCustomHeaders() {
suite.Run(s.T(), NewCustomHeadersScenario())
}

func TestTraefik2Suite(t *testing.T) {
suite.Run(t, NewTraefik2Suite())
}
4 changes: 4 additions & 0 deletions internal/suites/suite_traefik_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func (s *TraefikSuite) TestRedirectionURLScenario() {
suite.Run(s.T(), NewRedirectionURLScenario())
}

func (s *TraefikSuite) TestCustomHeaders() {
suite.Run(s.T(), NewCustomHeadersScenario())
}

func TestTraefikSuite(t *testing.T) {
suite.Run(t, NewTraefikSuite())
}