mirror of
https://github.com/greenpau/caddy-security.git
synced 2025-04-18 08:04:02 +03:00
865 lines
26 KiB
Go
865 lines
26 KiB
Go
// Copyright 2022 Paul Greenberg greenpau@outlook.com
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package security
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
|
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/greenpau/go-authcrunch/pkg/errors"
|
|
)
|
|
|
|
func TestParseCaddyfileAuthorization(t *testing.T) {
|
|
testcases := []struct {
|
|
name string
|
|
d *caddyfile.Dispenser
|
|
want string
|
|
shouldErr bool
|
|
err error
|
|
}{
|
|
{
|
|
name: "test valid authorization policy config",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
crypto key verify 0e2fdcf8-6868-41a7-884b-7308795fc286
|
|
set auth url /auth
|
|
allow roles authp/admin authp/user
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": [
|
|
"match roles authp/admin authp/user"
|
|
],
|
|
"action": "allow log debug"
|
|
}
|
|
],
|
|
"crypto_key_configs": [
|
|
{
|
|
"id": "0",
|
|
"usage": "verify",
|
|
"token_name": "access_token",
|
|
"source": "config",
|
|
"algorithm": "hmac",
|
|
"token_lifetime": 900,
|
|
"token_secret": "0e2fdcf8-6868-41a7-884b-7308795fc286"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy config with misc settings",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
crypto key verify 0e2fdcf8-6868-41a7-884b-7308795fc286
|
|
set auth url /auth
|
|
set token sources query
|
|
set forbidden url /forbidden
|
|
set redirect status 302
|
|
set redirect query parameter return_path_url
|
|
disable auth redirect query
|
|
disable auth redirect
|
|
validate path acl
|
|
validate source address
|
|
validate bearer header
|
|
with basic auth portal default realm local
|
|
with api key auth portal default realm local
|
|
allow roles authp/admin authp/user
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"disable_auth_redirect": true,
|
|
"disable_auth_redirect_query": true,
|
|
"auth_redirect_query_param": "return_path_url",
|
|
"auth_redirect_status_code": 302,
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": [
|
|
"match roles authp/admin authp/user"
|
|
],
|
|
"action": "allow log debug"
|
|
}
|
|
],
|
|
"crypto_key_configs": [
|
|
{
|
|
"id": "0",
|
|
"usage": "verify",
|
|
"token_name": "access_token",
|
|
"source": "config",
|
|
"algorithm": "hmac",
|
|
"token_lifetime": 900,
|
|
"token_secret": "0e2fdcf8-6868-41a7-884b-7308795fc286"
|
|
}
|
|
],
|
|
"auth_proxy_config": {
|
|
"portal_name": "default",
|
|
"basic_auth": {
|
|
"enabled": true,
|
|
"realms": {
|
|
"local": true
|
|
}
|
|
},
|
|
"api_key_auth": {
|
|
"enabled": true,
|
|
"realms": {
|
|
"local": true
|
|
}
|
|
}
|
|
},
|
|
"allowed_token_sources": [
|
|
"query"
|
|
],
|
|
"forbidden_url": "/forbidden",
|
|
"validate_bearer_header": true,
|
|
"validate_method_path": true,
|
|
"validate_access_list_path_claim": true,
|
|
"validate_source_address": true
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy config with custom acl",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy2 {
|
|
crypto key verify 0e2fdcf8-6868-41a7-884b-7308795fc286
|
|
bypass uri exact /foo
|
|
set user identity id
|
|
inject headers with claims
|
|
inject header "X-Picture" from picture
|
|
enable js redirect
|
|
set auth url /auth
|
|
enable strip token
|
|
enable additional scopes
|
|
acl rule {
|
|
comment allow users
|
|
match role authp/user
|
|
allow stop log info
|
|
}
|
|
acl rule {
|
|
comment default deny
|
|
match any
|
|
deny log warn
|
|
}
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy2",
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"redirect_with_javascript": true,
|
|
"access_list_rules": [
|
|
{
|
|
"comment": "comment allow users",
|
|
"conditions": [
|
|
"match role authp/user"
|
|
],
|
|
"action": "allow stop log info"
|
|
},
|
|
{
|
|
"comment": "comment default deny",
|
|
"conditions": [
|
|
"match any"
|
|
],
|
|
"action": "deny log warn"
|
|
}
|
|
],
|
|
"crypto_key_configs": [
|
|
{
|
|
"id": "0",
|
|
"usage": "verify",
|
|
"token_name": "access_token",
|
|
"source": "config",
|
|
"algorithm": "hmac",
|
|
"token_lifetime": 900,
|
|
"token_secret": "0e2fdcf8-6868-41a7-884b-7308795fc286"
|
|
}
|
|
],
|
|
"strip_token_enabled": true,
|
|
"additional_scopes": true,
|
|
"user_identity_field": "id",
|
|
"pass_claims_with_headers": true,
|
|
"redirect_with_javascript": true,
|
|
"header_injection_configs": [
|
|
{
|
|
"header": "X-Picture",
|
|
"field": "picture"
|
|
}
|
|
],
|
|
"bypass_configs": [
|
|
{
|
|
"match_type": "exact",
|
|
"uri": "/foo"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy with custom acl shortcuts",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
allow roles authp/admin authp/user
|
|
allow roles authp/guest with get to /foo
|
|
allow origin any
|
|
deny iss foo
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": ["match roles authp/admin authp/user"],
|
|
"action": "allow log debug"
|
|
},
|
|
{
|
|
"conditions": [
|
|
"match roles authp/guest",
|
|
"match method GET",
|
|
"partial match path /foo"
|
|
],
|
|
"action": "allow log debug"
|
|
},
|
|
{
|
|
"conditions": ["field origin exists"],
|
|
"action": "allow log debug"
|
|
},
|
|
{
|
|
"conditions": ["match iss foo"],
|
|
"action": "deny stop log warn"
|
|
}
|
|
],
|
|
"validate_method_path": true
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy with custom acl",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl rule {
|
|
match roles authp/admin authp/user
|
|
allow stop log info
|
|
}
|
|
acl default deny
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": ["match roles authp/admin authp/user"],
|
|
"action": "allow stop log info"
|
|
},
|
|
{
|
|
"conditions": ["match any"],
|
|
"action": "deny"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy with enabled login hint",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
enable login hint
|
|
allow roles authp/admin authp/user
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"login_hint_validators": ["email", "phone", "alphanumeric"],
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": [
|
|
"match roles authp/admin authp/user"
|
|
],
|
|
"action": "allow log debug"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test valid authorization policy with enabled login hint with validators",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
enable login hint with email phone
|
|
allow roles authp/admin authp/user
|
|
}
|
|
}`),
|
|
want: `{
|
|
"config": {
|
|
"authorization_policies": [
|
|
{
|
|
"name": "mypolicy",
|
|
"auth_url_path": "/auth",
|
|
"auth_redirect_query_param": "redirect_url",
|
|
"auth_redirect_status_code": 302,
|
|
"login_hint_validators": ["email", "phone"],
|
|
"access_list_rules": [
|
|
{
|
|
"conditions": [
|
|
"match roles authp/admin authp/user"
|
|
],
|
|
"action": "allow log debug"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}`,
|
|
},
|
|
{
|
|
name: "test malformed authorization policy definition",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy foo {
|
|
bypass uri /foo/bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("wrong argument count or unexpected line ending after '%s', at %s:%d", "foo", tf, 3),
|
|
},
|
|
{
|
|
name: "test unsupported authorization policy keyword",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
foo bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: errors.ErrMalformedDirective.WithArgs(
|
|
mkcp(authzPrefix, "policy", "foo"),
|
|
[]string{"bar"},
|
|
),
|
|
},
|
|
// Authorization header injection.
|
|
{
|
|
name: "test authorization policy injection with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
inject foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.inject: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy header injection with too many args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
inject header bar baz foo bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.inject directive %q is invalid, at %s:%d", "header bar baz foo bar", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy header injection with bad syntax",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
inject header "X-Picture" foo picture
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.inject directive %q has invalid syntax, at %s:%d", "header X-Picture foo picture", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy injection without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
inject
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.inject directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy injection without empty args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
inject header "X-Picture" from " "
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.inject %s erred: undefined field name, at %s:%d", "header X-Picture from \" \"", tf, 4),
|
|
},
|
|
// Enable features.
|
|
{
|
|
name: "test authorization policy enable without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
enable
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.enable directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy injection with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
enable foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.enable: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
// Validate features.
|
|
{
|
|
name: "test authorization policy validate without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
validate
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.validate directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy validate with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
validate foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.validate: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
// Disabled features.
|
|
{
|
|
name: "test authorization policy disable without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
disable
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.disable directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy disable with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
disable foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.disable: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
// Configure features.
|
|
{
|
|
name: "test authorization policy set without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
set
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.set directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy set with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
set foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.set: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy set redirect status success",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
set redirect status 200
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.set %v directive contains invalid value, at %s:%d", "redirect status 200", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy set redirect status alphanumeric",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
set redirect status foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.set %v directive failed: %v, at %s:%d",
|
|
"redirect status foo", "strconv.Atoi: parsing \"foo\": invalid syntax", tf, 4),
|
|
},
|
|
// With features.
|
|
{
|
|
name: "test authorization policy with without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
with
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("security.authorization.policy.with directive has no value, at %s:%d", tf, 4),
|
|
},
|
|
{
|
|
name: "test authorization policy with with unsupported directive",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
with foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf("unsupported directive for security.authorization.policy.with: %v, at %s:%d", "foo", tf, 4),
|
|
},
|
|
// Crypto errors.
|
|
{
|
|
name: "test authorization policy crypto with too little args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
crypto foo bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"%v, at %s:%d",
|
|
errors.ErrConfigDirectiveShort.WithArgs(
|
|
"security.authorization.policy.crypto",
|
|
[]string{"foo", "bar"},
|
|
), tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy crypto with unsupported args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
crypto foo bar baz
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"%v, at %s:%d",
|
|
errors.ErrConfigDirectiveValueUnsupported.WithArgs(
|
|
"security.authorization.policy.crypto",
|
|
[]string{"foo", "bar", "baz"},
|
|
), tf, 4,
|
|
),
|
|
},
|
|
// Bypass errors.
|
|
{
|
|
name: "test authorization policy bypass without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
bypass
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.bypass directive has no value, at %s:%d",
|
|
tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy bypass with wrong args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
bypass foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.bypass %s is invalid, at %s:%d",
|
|
"foo", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy bypass with invalid keyword",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
bypass foo bar baz
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.bypass %s is invalid, at %s:%d",
|
|
"foo bar baz", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy bypass with invalid syntax",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
bypass uri bar baz
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.bypass %s erred: %v, at %s:%d",
|
|
"uri bar baz", "invalid \"bar\" bypass match type", tf, 4,
|
|
),
|
|
},
|
|
// ACL errors.
|
|
{
|
|
name: "test authorization policy acl without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl directive has no value, at %s:%d",
|
|
tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl rule with args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl rule foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl directive %q is too long, at %s:%d",
|
|
"rule foo", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl default with args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl default allow bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl directive %q is too long, at %s:%d",
|
|
"default allow bar", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl default with args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl default foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl directive %q must have either allow or deny, at %s:%d",
|
|
"default foo", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl invalid",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl directive value of %q is unsupported, at %s:%d",
|
|
"foo", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl rule without comment value",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
acl rule {
|
|
comment
|
|
}
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.acl rule directive %v has no values, at %s:%d",
|
|
"comment", tf, 5,
|
|
),
|
|
},
|
|
// ACL shortcuts errors.
|
|
{
|
|
name: "test authorization policy acl shortcut without args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
allow
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.allow directive has no value, at %s:%d",
|
|
tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl shortcut without too few args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
allow foo
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.allow directive %q is too short, at %s:%d",
|
|
"foo", tf, 4,
|
|
),
|
|
},
|
|
{
|
|
name: "test authorization policy acl shortcut with unsupported args",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization policy mypolicy {
|
|
allow roles foo method get to /foo bar
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: fmt.Errorf(
|
|
"security.authorization.policy.allow directive value of %q is unsupported, at %s:%d",
|
|
"roles foo method get to /foo bar", tf, 4,
|
|
),
|
|
},
|
|
// Post config processing errors.
|
|
{
|
|
name: "test authorization invalid keyword",
|
|
d: caddyfile.NewTestDispenser(`
|
|
security {
|
|
authorization foo bar {
|
|
baz zag
|
|
}
|
|
}`),
|
|
shouldErr: true,
|
|
err: errors.ErrMalformedDirective.WithArgs(authzPrefix, []string{"foo", "bar"}),
|
|
},
|
|
}
|
|
for _, tc := range testcases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
app, err := parseCaddyfile(tc.d, nil)
|
|
if err != nil {
|
|
if !tc.shouldErr {
|
|
t.Fatalf("expected success, got: %v", err)
|
|
}
|
|
if diff := cmp.Diff(err.Error(), tc.err.Error()); diff != "" {
|
|
t.Fatalf("unexpected error: %v, want: %v", err, tc.err)
|
|
}
|
|
return
|
|
}
|
|
if tc.shouldErr {
|
|
t.Fatalf("unexpected success, want: %v", tc.err)
|
|
}
|
|
|
|
got := unpack(t, string(app.(httpcaddyfile.App).Value))
|
|
want := unpack(t, tc.want)
|
|
|
|
if diff := cmp.Diff(want, got); diff != "" {
|
|
t.Logf("JSON: %v", string(app.(httpcaddyfile.App).Value))
|
|
t.Errorf("parseCaddyfileAuthorization() mismatch (-want +got):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|