Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
c4e2e19e
Commit
c4e2e19e
authored
Nov 14, 2016
by
deads2k
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allow auth proxy to set groups and extra
parent
44f00e10
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
177 additions
and
22 deletions
+177
-22
builtin.go
pkg/apiserver/authenticator/builtin.go
+3
-0
requestheader.go
...auth/authenticator/request/headerrequest/requestheader.go
+90
-8
requestheader_test.go
...authenticator/request/headerrequest/requestheader_test.go
+84
-14
No files found.
pkg/apiserver/authenticator/builtin.go
View file @
c4e2e19e
...
...
@@ -88,6 +88,9 @@ func New(config AuthenticatorConfig) (authenticator.Request, *spec.SecurityDefin
config
.
RequestHeaderConfig
.
ClientCA
,
config
.
RequestHeaderConfig
.
AllowedClientNames
,
config
.
RequestHeaderConfig
.
UsernameHeaders
,
// TODO add wiring after options are refactored in 1.6
[]
string
{},
[]
string
{},
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
plugin/pkg/auth/authenticator/request/headerrequest/requestheader.go
View file @
c4e2e19e
...
...
@@ -33,23 +33,51 @@ import (
type
requestHeaderAuthRequestHandler
struct
{
// nameHeaders are the headers to check (in order, case-insensitively) for an identity. The first header with a value wins.
nameHeaders
[]
string
// groupHeaders are the headers to check (case-insensitively) for group membership. All values of all headers will be added.
groupHeaders
[]
string
// extraHeaderPrefixes are the head prefixes to check (case-insensitively) for filling in
// the user.Info.Extra. All values of all matching headers will be added.
extraHeaderPrefixes
[]
string
}
func
New
(
nameHeaders
[]
string
)
(
authenticator
.
Request
,
error
)
{
headers
:=
[]
string
{}
for
_
,
headerName
:=
range
nameHeaders
{
func
New
(
nameHeaders
[]
string
,
groupHeaders
[]
string
,
extraHeaderPrefixes
[]
string
)
(
authenticator
.
Request
,
error
)
{
trimmedNameHeaders
,
err
:=
trimHeaders
(
nameHeaders
...
)
if
err
!=
nil
{
return
nil
,
err
}
trimmedGroupHeaders
,
err
:=
trimHeaders
(
groupHeaders
...
)
if
err
!=
nil
{
return
nil
,
err
}
trimmedExtraHeaderPrefixes
,
err
:=
trimHeaders
(
extraHeaderPrefixes
...
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
requestHeaderAuthRequestHandler
{
nameHeaders
:
trimmedNameHeaders
,
groupHeaders
:
trimmedGroupHeaders
,
extraHeaderPrefixes
:
trimmedExtraHeaderPrefixes
,
},
nil
}
func
trimHeaders
(
headerNames
...
string
)
([]
string
,
error
)
{
ret
:=
[]
string
{}
for
_
,
headerName
:=
range
headerNames
{
trimmedHeader
:=
strings
.
TrimSpace
(
headerName
)
if
len
(
trimmedHeader
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"empty header %q"
,
headerName
)
}
headers
=
append
(
headers
,
trimmedHeader
)
ret
=
append
(
ret
,
trimmedHeader
)
}
return
&
requestHeaderAuthRequestHandler
{
nameHeaders
:
headers
}
,
nil
return
ret
,
nil
}
func
NewSecure
(
clientCA
string
,
proxyClientNames
[]
string
,
nameHeaders
[]
string
)
(
authenticator
.
Request
,
error
)
{
headerAuthenticator
,
err
:=
New
(
nameHeaders
)
func
NewSecure
(
clientCA
string
,
proxyClientNames
[]
string
,
nameHeaders
[]
string
,
groupHeaders
[]
string
,
extraHeaderPrefixes
[]
string
)
(
authenticator
.
Request
,
error
)
{
headerAuthenticator
,
err
:=
New
(
nameHeaders
,
groupHeaders
,
extraHeaderPrefixes
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -81,8 +109,27 @@ func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request)
if
len
(
name
)
==
0
{
return
nil
,
false
,
nil
}
groups
:=
allHeaderValues
(
req
.
Header
,
a
.
groupHeaders
)
extra
:=
newExtra
(
req
.
Header
,
a
.
extraHeaderPrefixes
)
// clear headers used for authentication
for
_
,
headerName
:=
range
a
.
nameHeaders
{
req
.
Header
.
Del
(
headerName
)
}
for
_
,
headerName
:=
range
a
.
groupHeaders
{
req
.
Header
.
Del
(
headerName
)
}
for
k
:=
range
extra
{
for
_
,
prefix
:=
range
a
.
extraHeaderPrefixes
{
req
.
Header
.
Del
(
prefix
+
k
)
}
}
return
&
user
.
DefaultInfo
{
Name
:
name
},
true
,
nil
return
&
user
.
DefaultInfo
{
Name
:
name
,
Groups
:
groups
,
Extra
:
extra
,
},
true
,
nil
}
func
headerValue
(
h
http
.
Header
,
headerNames
[]
string
)
string
{
...
...
@@ -94,3 +141,38 @@ func headerValue(h http.Header, headerNames []string) string {
}
return
""
}
func
allHeaderValues
(
h
http
.
Header
,
headerNames
[]
string
)
[]
string
{
ret
:=
[]
string
{}
for
_
,
headerName
:=
range
headerNames
{
values
,
ok
:=
h
[
headerName
]
if
!
ok
{
continue
}
for
_
,
headerValue
:=
range
values
{
if
len
(
headerValue
)
>
0
{
ret
=
append
(
ret
,
headerValue
)
}
}
}
return
ret
}
func
newExtra
(
h
http
.
Header
,
headerPrefixes
[]
string
)
map
[
string
][]
string
{
ret
:=
map
[
string
][]
string
{}
// we have to iterate over prefixes first in order to have proper ordering inside the value slices
for
_
,
prefix
:=
range
headerPrefixes
{
for
headerName
,
vv
:=
range
h
{
if
!
strings
.
HasPrefix
(
strings
.
ToLower
(
headerName
),
strings
.
ToLower
(
prefix
))
{
continue
}
extraKey
:=
strings
.
ToLower
(
headerName
[
len
(
prefix
)
:
])
ret
[
extraKey
]
=
append
(
ret
[
extraKey
],
vv
...
)
}
}
return
ret
}
plugin/pkg/auth/authenticator/request/headerrequest/requestheader_test.go
View file @
c4e2e19e
...
...
@@ -26,30 +26,36 @@ import (
func
TestRequestHeader
(
t
*
testing
.
T
)
{
testcases
:=
map
[
string
]
struct
{
nameHeaders
[]
string
requestHeaders
http
.
Header
nameHeaders
[]
string
groupHeaders
[]
string
extraPrefixHeaders
[]
string
requestHeaders
http
.
Header
expectedUser
user
.
Info
expectedOk
bool
}{
"empty"
:
{},
"no match"
:
{
"
user
no match"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
},
"match"
:
{
"
user
match"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
requestHeaders
:
http
.
Header
{
"X-Remote-User"
:
{
"Bob"
}},
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
},
expectedOk
:
true
,
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
,
Groups
:
[]
string
{},
Extra
:
map
[
string
][]
string
{},
},
expectedOk
:
true
,
},
"exact match"
:
{
"
user
exact match"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
requestHeaders
:
http
.
Header
{
"Prefixed-X-Remote-User-With-Suffix"
:
{
"Bob"
},
"X-Remote-User-With-Suffix"
:
{
"Bob"
},
},
},
"first match"
:
{
"
user
first match"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
,
"A-Second-X-Remote-User"
,
...
...
@@ -59,19 +65,83 @@ func TestRequestHeader(t *testing.T) {
"X-Remote-User"
:
{
""
,
"First header, second value"
},
"A-Second-X-Remote-User"
:
{
"Second header, first value"
,
"Second header, second value"
},
"Another-X-Remote-User"
:
{
"Third header, first value"
}},
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Second header, first value"
},
expectedOk
:
true
,
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Second header, first value"
,
Groups
:
[]
string
{},
Extra
:
map
[
string
][]
string
{},
},
expectedOk
:
true
,
},
"case-insensitive"
:
{
"
user
case-insensitive"
:
{
nameHeaders
:
[]
string
{
"x-REMOTE-user"
},
// configured headers can be case-insensitive
requestHeaders
:
http
.
Header
{
"X-Remote-User"
:
{
"Bob"
}},
// the parsed headers are normalized by the http package
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
},
expectedOk
:
true
,
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
,
Groups
:
[]
string
{},
Extra
:
map
[
string
][]
string
{},
},
expectedOk
:
true
,
},
"groups none"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
groupHeaders
:
[]
string
{
"X-Remote-Group"
},
requestHeaders
:
http
.
Header
{
"X-Remote-User"
:
{
"Bob"
},
},
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
,
Groups
:
[]
string
{},
Extra
:
map
[
string
][]
string
{},
},
expectedOk
:
true
,
},
"groups all matches"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
groupHeaders
:
[]
string
{
"X-Remote-Group-1"
,
"X-Remote-Group-2"
},
requestHeaders
:
http
.
Header
{
"X-Remote-User"
:
{
"Bob"
},
"X-Remote-Group-1"
:
{
"one-a"
,
"one-b"
},
"X-Remote-Group-2"
:
{
"two-a"
,
"two-b"
},
},
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
,
Groups
:
[]
string
{
"one-a"
,
"one-b"
,
"two-a"
,
"two-b"
},
Extra
:
map
[
string
][]
string
{},
},
expectedOk
:
true
,
},
"extra prefix matches case-insensitive"
:
{
nameHeaders
:
[]
string
{
"X-Remote-User"
},
groupHeaders
:
[]
string
{
"X-Remote-Group-1"
,
"X-Remote-Group-2"
},
extraPrefixHeaders
:
[]
string
{
"X-Remote-Extra-1-"
,
"X-Remote-Extra-2-"
},
requestHeaders
:
http
.
Header
{
"X-Remote-User"
:
{
"Bob"
},
"X-Remote-Group-1"
:
{
"one-a"
,
"one-b"
},
"X-Remote-Group-2"
:
{
"two-a"
,
"two-b"
},
"X-Remote-extra-1-key1"
:
{
"alfa"
,
"bravo"
},
"X-Remote-Extra-1-Key2"
:
{
"charlie"
,
"delta"
},
"X-Remote-Extra-1-"
:
{
"india"
,
"juliet"
},
"X-Remote-extra-2-"
:
{
"kilo"
,
"lima"
},
"X-Remote-extra-2-Key1"
:
{
"echo"
,
"foxtrot"
},
"X-Remote-Extra-2-key2"
:
{
"golf"
,
"hotel"
},
},
expectedUser
:
&
user
.
DefaultInfo
{
Name
:
"Bob"
,
Groups
:
[]
string
{
"one-a"
,
"one-b"
,
"two-a"
,
"two-b"
},
Extra
:
map
[
string
][]
string
{
"key1"
:
{
"alfa"
,
"bravo"
,
"echo"
,
"foxtrot"
},
"key2"
:
{
"charlie"
,
"delta"
,
"golf"
,
"hotel"
},
""
:
{
"india"
,
"juliet"
,
"kilo"
,
"lima"
},
},
},
expectedOk
:
true
,
},
}
for
k
,
testcase
:=
range
testcases
{
auth
,
err
:=
New
(
testcase
.
nameHeaders
)
auth
,
err
:=
New
(
testcase
.
nameHeaders
,
testcase
.
groupHeaders
,
testcase
.
extraPrefixHeaders
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment