Skip to content

Commit

Permalink
Merge pull request #41 from deflect-ca/feature/per-site-cookie-ttl
Browse files Browse the repository at this point in the history
Support per site password expire time
  • Loading branch information
jeremy5189 authored Sep 14, 2023
2 parents cc866d4 + bb2ba57 commit e362653
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 7 deletions.
2 changes: 2 additions & 0 deletions banjax-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ password_hashes:
"localhost": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
password_hash_roaming:
sub.example.com: example.com
password_persite_cookie_ttl_seconds:
example.com: 3600
per_site_decision_lists:
example.com:
allow:
Expand Down
10 changes: 7 additions & 3 deletions banjax_base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func httpCheck(client *http.Client, resource_ptr *TestResource, t *testing.T) {
}
}

type CookieMap map[string]string
type CookieMap map[string]*http.Cookie

func httpTesterWithCookie(t *testing.T, resources []TestResource) {
client := &http.Client{}
Expand All @@ -128,6 +128,11 @@ func httpTesterWithCookie(t *testing.T, resources []TestResource) {
t.Run(test_name, func(t *testing.T) {
cookies := httpCheckWithCookie(client, &resource, t)
assert.Contains(t, cookies, resource.contains[0])
if len(resource.contains) > 1 {
log.Print(cookies[resource.contains[0]])
expectedMaxAge, _ := strconv.Atoi(resource.contains[1])
assert.Equal(t, cookies[resource.contains[0]].MaxAge, expectedMaxAge)
}
})
}
}
Expand All @@ -140,9 +145,8 @@ func httpCheckWithCookie(client *http.Client, resource_ptr *TestResource, t *tes

cookieMap = make(CookieMap)
if len(resp.Cookies()) > 0 {
log.Print(resp.Cookies())
for _, cookie := range resp.Cookies() {
cookieMap[cookie.Name] = cookie.Value
cookieMap[cookie.Name] = cookie
}
}

Expand Down
7 changes: 7 additions & 0 deletions banjax_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ func TestPathWithChallengeCookies(t *testing.T) {
prefix := "/auth_request?path="
httpTesterWithCookie(t, []TestResource{
{"GET", prefix + "/wp-admin", 401, nil, []string{"deflect_password3"}},
{"GET", prefix + "/wp-admin", 401, nil, []string{"deflect_password3", "3600"}}, // testing max-age
{"GET", prefix + "/global_mask_64_ban", 429, ClientIP("192.168.1.64"), []string{"deflect_challenge3"}},
})

// reload without per site max age, test if default value 14400 present
reloadConfig(fixtureConfigTestReloadCIDR, 1)
httpTesterWithCookie(t, []TestResource{
{"GET", prefix + "/wp-admin", 401, nil, []string{"deflect_password3", "14400"}}, // testing max-age
})
}

func TestGlobalPerSiteDecisionListsMask(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions fixtures/banjax-config-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ password_protected_path_exceptions:
password_hashes:
"localhost:8081": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
"localhost": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
password_persite_cookie_ttl_seconds:
"localhost:8081": 3600
per_site_decision_lists:
example.com:
allow:
Expand Down
1 change: 1 addition & 0 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Config struct {
SitesToProtectedPaths map[string][]string `yaml:"password_protected_paths"`
SitesToProtectedPathExceptions map[string][]string `yaml:"password_protected_path_exceptions"`
SitesToPasswordHashesRoaming map[string]string `yaml:"password_hash_roaming"`
SitesToPasswordCookieTtlSeconds map[string]int `yaml:"password_persite_cookie_ttl_seconds"`
ExpiringDecisionTtlSeconds int `yaml:"expiring_decision_ttl_seconds"`
TooManyFailedChallengesIntervalSeconds int `yaml:"too_many_failed_challenges_interval_seconds"`
TooManyFailedChallengesThreshold int `yaml:"too_many_failed_challenges_threshold"`
Expand Down
17 changes: 13 additions & 4 deletions internal/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,10 @@ func challenge(c *gin.Context, cookieName string, cookieTtlSeconds int, secret s
}

func passwordChallenge(c *gin.Context, config *Config, roaming bool) {
challenge(c, "deflect_password3", config.PasswordCookieTtlSeconds, config.HmacSecret, roaming)
cookieTtl := getPerSiteCookieTtlOrDefault(config, c.Request.Header.Get("X-Requested-Host"), config.PasswordCookieTtlSeconds)
challenge(c, "deflect_password3", cookieTtl, config.HmacSecret, roaming)
// custom status code, not defined in RFC
c.Data(401, "text/html", applyArgsToPasswordPage(config, config.PasswordPageBytes, roaming))
c.Data(401, "text/html", applyArgsToPasswordPage(config, config.PasswordPageBytes, roaming, cookieTtl))
c.Abort()
}

Expand All @@ -247,6 +248,14 @@ func shaInvChallenge(c *gin.Context, config *Config) {
c.Abort()
}

func getPerSiteCookieTtlOrDefault(config *Config, domain string, defaultTtl int) (cookieTtl int) {
cookieTtl, ok := config.SitesToPasswordCookieTtlSeconds[domain]
if ok {
return
}
return defaultTtl
}

func modifyHTMLContent(pageBytes []byte, targetStr string, toReplace string) (modifiedPageBytes []byte) {
return bytes.Replace(pageBytes, []byte(targetStr), []byte(toReplace), 1)
}
Expand Down Expand Up @@ -275,9 +284,9 @@ func applyCookieDomain(pageBytes []byte, cookieName string) (modifiedPageBytes [
)
}

func applyArgsToPasswordPage(config *Config, pageBytes []byte, roaming bool) (modifiedPageBytes []byte) {
func applyArgsToPasswordPage(config *Config, pageBytes []byte, roaming bool, cookieTtl int) (modifiedPageBytes []byte) {
// apply default or site specific expire time
modifiedPageBytes = applyCookieMaxAge(pageBytes, "deflect_password3", config.PasswordCookieTtlSeconds)
modifiedPageBytes = applyCookieMaxAge(pageBytes, "deflect_password3", cookieTtl)

if !roaming {
return
Expand Down

0 comments on commit e362653

Please sign in to comment.