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
27cf50d8
Unverified
Commit
27cf50d8
authored
Nov 12, 2018
by
k8s-ci-robot
Committed by
GitHub
Nov 12, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #70322 from mikedanese/audoidc
make oidc authenticator (more?) audience aware
parents
3c5c6025
a714d9cd
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
187 additions
and
20 deletions
+187
-20
config.go
pkg/kubeapiserver/authenticator/config.go
+20
-19
BUILD
...8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD
+1
-0
oidc.go
....io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go
+15
-0
oidc_test.go
...piserver/plugin/pkg/authenticator/token/oidc/oidc_test.go
+151
-1
No files found.
pkg/kubeapiserver/authenticator/config.go
View file @
27cf50d8
...
@@ -161,7 +161,18 @@ func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, er
...
@@ -161,7 +161,18 @@ func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, er
// simply returns an error, the OpenID Connect plugin may query the provider to
// simply returns an error, the OpenID Connect plugin may query the provider to
// update the keys, causing performance hits.
// update the keys, causing performance hits.
if
len
(
config
.
OIDCIssuerURL
)
>
0
&&
len
(
config
.
OIDCClientID
)
>
0
{
if
len
(
config
.
OIDCIssuerURL
)
>
0
&&
len
(
config
.
OIDCClientID
)
>
0
{
oidcAuth
,
err
:=
newAuthenticatorFromOIDCIssuerURL
(
config
.
OIDCIssuerURL
,
config
.
OIDCClientID
,
config
.
OIDCCAFile
,
config
.
OIDCUsernameClaim
,
config
.
OIDCUsernamePrefix
,
config
.
OIDCGroupsClaim
,
config
.
OIDCGroupsPrefix
,
config
.
OIDCSigningAlgs
,
config
.
OIDCRequiredClaims
)
oidcAuth
,
err
:=
newAuthenticatorFromOIDCIssuerURL
(
oidc
.
Options
{
IssuerURL
:
config
.
OIDCIssuerURL
,
ClientID
:
config
.
OIDCClientID
,
APIAudiences
:
config
.
APIAudiences
,
CAFile
:
config
.
OIDCCAFile
,
UsernameClaim
:
config
.
OIDCUsernameClaim
,
UsernamePrefix
:
config
.
OIDCUsernamePrefix
,
GroupsClaim
:
config
.
OIDCGroupsClaim
,
GroupsPrefix
:
config
.
OIDCGroupsPrefix
,
SupportedSigningAlgs
:
config
.
OIDCSigningAlgs
,
RequiredClaims
:
config
.
OIDCRequiredClaims
,
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
...
@@ -240,33 +251,23 @@ func newAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Token, e
...
@@ -240,33 +251,23 @@ func newAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Token, e
}
}
// newAuthenticatorFromOIDCIssuerURL returns an authenticator.Token or an error.
// newAuthenticatorFromOIDCIssuerURL returns an authenticator.Token or an error.
func
newAuthenticatorFromOIDCIssuerURL
(
issuerURL
,
clientID
,
caFile
,
usernameClaim
,
usernamePrefix
,
groupsClaim
,
groupsPrefix
string
,
signingAlgs
[]
string
,
requiredClaims
map
[
string
]
string
)
(
authenticator
.
Token
,
error
)
{
func
newAuthenticatorFromOIDCIssuerURL
(
opts
oidc
.
Options
)
(
authenticator
.
Token
,
error
)
{
const
noUsernamePrefix
=
"-"
const
noUsernamePrefix
=
"-"
if
usernamePrefix
==
""
&&
u
sernameClaim
!=
"email"
{
if
opts
.
UsernamePrefix
==
""
&&
opts
.
U
sernameClaim
!=
"email"
{
// Old behavior. If a usernamePrefix isn't provided, prefix all claims other than "email"
// Old behavior. If a usernamePrefix isn't provided, prefix all claims other than "email"
// with the issuerURL.
// with the issuerURL.
//
//
// See https://github.com/kubernetes/kubernetes/issues/31380
// See https://github.com/kubernetes/kubernetes/issues/31380
usernamePrefix
=
i
ssuerURL
+
"#"
opts
.
UsernamePrefix
=
opts
.
I
ssuerURL
+
"#"
}
}
if
u
sernamePrefix
==
noUsernamePrefix
{
if
opts
.
U
sernamePrefix
==
noUsernamePrefix
{
// Special value indicating usernames shouldn't be prefixed.
// Special value indicating usernames shouldn't be prefixed.
usernamePrefix
=
""
opts
.
UsernamePrefix
=
""
}
}
tokenAuthenticator
,
err
:=
oidc
.
New
(
oidc
.
Options
{
tokenAuthenticator
,
err
:=
oidc
.
New
(
opts
)
IssuerURL
:
issuerURL
,
ClientID
:
clientID
,
CAFile
:
caFile
,
UsernameClaim
:
usernameClaim
,
UsernamePrefix
:
usernamePrefix
,
GroupsClaim
:
groupsClaim
,
GroupsPrefix
:
groupsPrefix
,
SupportedSigningAlgs
:
signingAlgs
,
RequiredClaims
:
requiredClaims
,
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/BUILD
View file @
27cf50d8
...
@@ -13,6 +13,7 @@ go_test(
...
@@ -13,6 +13,7 @@ go_test(
data = glob(["testdata/**"]),
data = glob(["testdata/**"]),
embed = [":go_default_library"],
embed = [":go_default_library"],
deps = [
deps = [
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/github.com/coreos/go-oidc:go_default_library",
"//vendor/github.com/coreos/go-oidc:go_default_library",
"//vendor/gopkg.in/square/go-jose.v2:go_default_library",
"//vendor/gopkg.in/square/go-jose.v2:go_default_library",
...
...
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go
View file @
27cf50d8
...
@@ -78,6 +78,12 @@ type Options struct {
...
@@ -78,6 +78,12 @@ type Options struct {
// See: https://openid.net/specs/openid-connect-core-1_0.html#IDToken
// See: https://openid.net/specs/openid-connect-core-1_0.html#IDToken
ClientID
string
ClientID
string
// APIAudiences are the audiences that the API server identitifes as. The
// (API audiences unioned with the ClientIDs) should have a non-empty
// intersection with the request's target audience. This preserves the
// behavior of the OIDC authenticator pre-introduction of API audiences.
APIAudiences
authenticator
.
Audiences
// Path to a PEM encoded root certificate of the provider.
// Path to a PEM encoded root certificate of the provider.
CAFile
string
CAFile
string
...
@@ -188,6 +194,8 @@ type Authenticator struct {
...
@@ -188,6 +194,8 @@ type Authenticator struct {
groupsClaim
string
groupsClaim
string
groupsPrefix
string
groupsPrefix
string
requiredClaims
map
[
string
]
string
requiredClaims
map
[
string
]
string
clientIDs
authenticator
.
Audiences
apiAudiences
authenticator
.
Audiences
// Contains an *oidc.IDTokenVerifier. Do not access directly use the
// Contains an *oidc.IDTokenVerifier. Do not access directly use the
// idTokenVerifier method.
// idTokenVerifier method.
...
@@ -317,6 +325,8 @@ func newAuthenticator(opts Options, initVerifier func(ctx context.Context, a *Au
...
@@ -317,6 +325,8 @@ func newAuthenticator(opts Options, initVerifier func(ctx context.Context, a *Au
groupsClaim
:
opts
.
GroupsClaim
,
groupsClaim
:
opts
.
GroupsClaim
,
groupsPrefix
:
opts
.
GroupsPrefix
,
groupsPrefix
:
opts
.
GroupsPrefix
,
requiredClaims
:
opts
.
RequiredClaims
,
requiredClaims
:
opts
.
RequiredClaims
,
clientIDs
:
authenticator
.
Audiences
{
opts
.
ClientID
},
apiAudiences
:
opts
.
APIAudiences
,
cancel
:
cancel
,
cancel
:
cancel
,
resolver
:
resolver
,
resolver
:
resolver
,
}
}
...
@@ -532,6 +542,11 @@ func (r *claimResolver) resolve(endpoint endpoint, allClaims claims) error {
...
@@ -532,6 +542,11 @@ func (r *claimResolver) resolve(endpoint endpoint, allClaims claims) error {
}
}
func
(
a
*
Authenticator
)
AuthenticateToken
(
ctx
context
.
Context
,
token
string
)
(
*
authenticator
.
Response
,
bool
,
error
)
{
func
(
a
*
Authenticator
)
AuthenticateToken
(
ctx
context
.
Context
,
token
string
)
(
*
authenticator
.
Response
,
bool
,
error
)
{
if
reqAuds
,
ok
:=
authenticator
.
AudiencesFrom
(
ctx
);
ok
{
if
len
(
reqAuds
.
Intersect
(
a
.
clientIDs
))
==
0
&&
len
(
reqAuds
.
Intersect
(
a
.
apiAudiences
))
==
0
{
return
nil
,
false
,
nil
}
}
if
!
hasCorrectIssuer
(
a
.
issuerURL
,
token
)
{
if
!
hasCorrectIssuer
(
a
.
issuerURL
,
token
)
{
return
nil
,
false
,
nil
return
nil
,
false
,
nil
}
}
...
...
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc_test.go
View file @
27cf50d8
...
@@ -37,6 +37,8 @@ import (
...
@@ -37,6 +37,8 @@ import (
oidc
"github.com/coreos/go-oidc"
oidc
"github.com/coreos/go-oidc"
jose
"gopkg.in/square/go-jose.v2"
jose
"gopkg.in/square/go-jose.v2"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/klog"
"k8s.io/klog"
)
)
...
@@ -140,6 +142,7 @@ type claimsTest struct {
...
@@ -140,6 +142,7 @@ type claimsTest struct {
wantInitErr
bool
wantInitErr
bool
claimToResponseMap
map
[
string
]
string
claimToResponseMap
map
[
string
]
string
openIDConfig
string
openIDConfig
string
reqAudiences
authenticator
.
Audiences
}
}
// Replace formats the contents of v into the provided template.
// Replace formats the contents of v into the provided template.
...
@@ -296,7 +299,12 @@ func (c *claimsTest) run(t *testing.T) {
...
@@ -296,7 +299,12 @@ func (c *claimsTest) run(t *testing.T) {
t
.
Fatalf
(
"serialize token: %v"
,
err
)
t
.
Fatalf
(
"serialize token: %v"
,
err
)
}
}
got
,
ok
,
err
:=
a
.
AuthenticateToken
(
context
.
Background
(),
token
)
ctx
:=
context
.
Background
()
if
c
.
reqAudiences
!=
nil
{
ctx
=
authenticator
.
WithAudiences
(
ctx
,
c
.
reqAudiences
)
}
got
,
ok
,
err
:=
a
.
AuthenticateToken
(
ctx
,
token
)
if
err
!=
nil
{
if
err
!=
nil
{
if
!
c
.
wantErr
{
if
!
c
.
wantErr
{
...
@@ -1388,6 +1396,148 @@ func TestToken(t *testing.T) {
...
@@ -1388,6 +1396,148 @@ func TestToken(t *testing.T) {
Name
:
"thomas.jefferson@gmail.com"
,
Name
:
"thomas.jefferson@gmail.com"
,
},
},
},
},
{
name
:
"good token with api req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"api"
},
want
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
},
},
{
name
:
"good token with multiple api req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
,
"other"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"api"
},
want
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
},
},
{
name
:
"good token with client_id req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"my-client"
},
want
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
},
},
{
name
:
"good token with client_id and api req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"my-client"
,
"api"
},
want
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
},
},
{
name
:
"good token with client_id and api req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"my-client"
,
"api"
},
want
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
},
},
{
name
:
"good token with client_id and bad req audience"
,
options
:
Options
{
IssuerURL
:
"https://auth.example.com"
,
ClientID
:
"my-client"
,
APIAudiences
:
authenticator
.
Audiences
{
"api"
},
UsernameClaim
:
"username"
,
now
:
func
()
time
.
Time
{
return
now
},
},
signingKey
:
loadRSAPrivKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
pubKeys
:
[]
*
jose
.
JSONWebKey
{
loadRSAKey
(
t
,
"testdata/rsa_1.pem"
,
jose
.
RS256
),
},
claims
:
fmt
.
Sprintf
(
`{
"iss": "https://auth.example.com",
"aud": "my-client",
"username": "jane",
"exp": %d
}`
,
valid
.
Unix
()),
reqAudiences
:
authenticator
.
Audiences
{
"other"
},
wantSkip
:
true
,
},
}
}
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
t
.
Run
(
test
.
name
,
test
.
run
)
t
.
Run
(
test
.
name
,
test
.
run
)
...
...
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