Skip to content

Commit 446a3fe

Browse files
Merge pull request #16110 from deads2k/server-40-normal-authz
Automatic merge from submit-queue use the upstream authorization filters This brings in a config option from upstream and uses it to remove custom handler code we had. @openshift/sig-security
2 parents 074acdc + 5f83f0c commit 446a3fe

21 files changed

+70
-154
lines changed

pkg/authorization/authorizer/attributes_builder.go

Lines changed: 0 additions & 53 deletions
This file was deleted.

pkg/authorization/authorizer/browser_safe_request_info_resolver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
type browserSafeRequestInfoResolver struct {
1111
// infoFactory is used to determine info for the request
12-
infoFactory RequestInfoFactory
12+
infoFactory apirequest.RequestInfoResolver
1313

1414
// contextMapper is used to look up the context corresponding to a request
1515
// to obtain the user associated with the request
@@ -19,7 +19,7 @@ type browserSafeRequestInfoResolver struct {
1919
authenticatedGroups sets.String
2020
}
2121

22-
func NewBrowserSafeRequestInfoResolver(contextMapper apirequest.RequestContextMapper, authenticatedGroups sets.String, infoFactory RequestInfoFactory) RequestInfoFactory {
22+
func NewBrowserSafeRequestInfoResolver(contextMapper apirequest.RequestContextMapper, authenticatedGroups sets.String, infoFactory apirequest.RequestInfoResolver) apirequest.RequestInfoResolver {
2323
return &browserSafeRequestInfoResolver{
2424
contextMapper: contextMapper,
2525
authenticatedGroups: authenticatedGroups,

pkg/authorization/authorizer/interfaces.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
package authorizer
22

33
import (
4-
"net/http"
5-
64
"k8s.io/apimachinery/pkg/util/sets"
75
"k8s.io/apiserver/pkg/authorization/authorizer"
8-
apirequest "k8s.io/apiserver/pkg/endpoints/request"
96
)
107

118
type SubjectLocator interface {
129
GetAllowedSubjects(attributes authorizer.Attributes) (sets.String, sets.String, error)
1310
}
1411

15-
type AuthorizationAttributeBuilder interface {
16-
GetAttributes(request *http.Request) (authorizer.Attributes, error)
17-
}
18-
19-
type RequestInfoFactory interface {
20-
NewRequestInfo(req *http.Request) (*apirequest.RequestInfo, error)
21-
}
22-
2312
// ForbiddenMessageMaker creates a forbidden message from Attributes
2413
type ForbiddenMessageMaker interface {
2514
MakeMessage(attrs authorizer.Attributes) (string, error)

pkg/authorization/authorizer/personal_subjectaccessreview.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ import (
88

99
"k8s.io/apimachinery/pkg/runtime/schema"
1010
"k8s.io/apiserver/pkg/endpoints/request"
11+
apirequest "k8s.io/apiserver/pkg/endpoints/request"
1112
kapi "k8s.io/kubernetes/pkg/api"
1213

1314
authorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
1415
)
1516

1617
type personalSARRequestInfoResolver struct {
1718
// infoFactory is used to determine info for the request
18-
infoFactory RequestInfoFactory
19+
infoFactory apirequest.RequestInfoResolver
1920
}
2021

21-
func NewPersonalSARRequestInfoResolver(infoFactory RequestInfoFactory) RequestInfoFactory {
22+
func NewPersonalSARRequestInfoResolver(infoFactory apirequest.RequestInfoResolver) apirequest.RequestInfoResolver {
2223
return &personalSARRequestInfoResolver{
2324
infoFactory: infoFactory,
2425
}

pkg/authorization/authorizer/project_request_info_resolver.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ package authorizer
33
import (
44
"net/http"
55

6-
"k8s.io/apiserver/pkg/endpoints/request"
6+
apirequest "k8s.io/apiserver/pkg/endpoints/request"
77
)
88

99
type projectRequestInfoResolver struct {
1010
// infoFactory is used to determine info for the request
11-
infoFactory RequestInfoFactory
11+
infoFactory apirequest.RequestInfoResolver
1212
}
1313

14-
func NewProjectRequestInfoResolver(infoFactory RequestInfoFactory) RequestInfoFactory {
14+
func NewProjectRequestInfoResolver(infoFactory apirequest.RequestInfoResolver) apirequest.RequestInfoResolver {
1515
return &projectRequestInfoResolver{
1616
infoFactory: infoFactory,
1717
}
1818
}
1919

20-
func (a *projectRequestInfoResolver) NewRequestInfo(req *http.Request) (*request.RequestInfo, error) {
20+
func (a *projectRequestInfoResolver) NewRequestInfo(req *http.Request) (*apirequest.RequestInfo, error) {
2121
requestInfo, err := a.infoFactory.NewRequestInfo(req)
2222
if err != nil {
2323
return requestInfo, err

pkg/cmd/server/handlers/authorization.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import (
1414
"k8s.io/apimachinery/pkg/runtime/schema"
1515
"k8s.io/apimachinery/pkg/util/sets"
1616
kauthorizer "k8s.io/apiserver/pkg/authorization/authorizer"
17-
apirequest "k8s.io/apiserver/pkg/endpoints/request"
1817
kapi "k8s.io/kubernetes/pkg/api"
19-
20-
"github.com/openshift/origin/pkg/authorization/authorizer"
2118
)
2219

2320
type bypassAuthorizer struct {
@@ -38,33 +35,6 @@ func (a bypassAuthorizer) Authorize(attributes kauthorizer.Attributes) (allowed
3835
return a.authorizer.Authorize(attributes)
3936
}
4037

41-
// AuthorizationFilter imposes normal authorization rules
42-
func AuthorizationFilter(handler http.Handler, authorizer kauthorizer.Authorizer, authorizationAttributeBuilder authorizer.AuthorizationAttributeBuilder, contextMapper apirequest.RequestContextMapper) http.Handler {
43-
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
44-
attributes, err := authorizationAttributeBuilder.GetAttributes(req)
45-
if err != nil {
46-
Forbidden(err.Error(), attributes, w, req)
47-
return
48-
}
49-
if attributes == nil {
50-
Forbidden("No attributes", attributes, w, req)
51-
return
52-
}
53-
54-
allowed, reason, err := authorizer.Authorize(attributes)
55-
if err != nil {
56-
Forbidden(err.Error(), attributes, w, req)
57-
return
58-
}
59-
if !allowed {
60-
Forbidden(reason, attributes, w, req)
61-
return
62-
}
63-
64-
handler.ServeHTTP(w, req)
65-
})
66-
}
67-
6838
// Forbidden renders a simple forbidden error to the response
6939
func Forbidden(reason string, attributes kauthorizer.Attributes, w http.ResponseWriter, req *http.Request) {
7040
kind := ""

pkg/cmd/server/kubernetes/master/master_config.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ import (
5959
kversion "k8s.io/kubernetes/pkg/version"
6060

6161
"github.com/openshift/origin/pkg/api"
62+
oauthorizer "github.com/openshift/origin/pkg/authorization/authorizer"
6263
"github.com/openshift/origin/pkg/authorization/authorizer/scope"
6364
"github.com/openshift/origin/pkg/cmd/flagtypes"
6465
configapi "github.com/openshift/origin/pkg/cmd/server/api"
66+
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
6567
"github.com/openshift/origin/pkg/cmd/server/cm"
6668
"github.com/openshift/origin/pkg/cmd/server/crypto"
6769
"github.com/openshift/origin/pkg/cmd/server/election"
@@ -449,6 +451,7 @@ func buildKubeApiserverConfig(
449451
genericConfig.DisabledPostStartHooks.Insert("extensions/third-party-resources")
450452
genericConfig.AdmissionControl = admissionControl
451453
genericConfig.RequestContextMapper = requestContextMapper
454+
genericConfig.RequestInfoResolver = openshiftRequestInfoResolver(genericConfig.RequestContextMapper)
452455
genericConfig.OpenAPIConfig = defaultOpenAPIConfig(masterConfig)
453456
genericConfig.SwaggerConfig = apiserver.DefaultSwaggerConfig()
454457
genericConfig.SwaggerConfig.PostBuildHandler = customizeSwaggerDefinition
@@ -781,3 +784,18 @@ func readCAorNil(file string) ([]byte, error) {
781784
func newMasterLeases(storage storage.Interface, masterEndpointReconcileTTL int) election.Leases {
782785
return election.NewLeases(storage, "/masterleases/", uint64(masterEndpointReconcileTTL))
783786
}
787+
788+
func openshiftRequestInfoResolver(requestContextMapper apirequest.RequestContextMapper) apirequest.RequestInfoResolver {
789+
// Default API request info factory
790+
requestInfoFactory := &apirequest.RequestInfoFactory{APIPrefixes: sets.NewString("api", "osapi", "oapi", "apis"), GrouplessAPIPrefixes: sets.NewString("api", "osapi", "oapi")}
791+
// Wrap with a request info factory that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately
792+
browserSafeRequestInfoResolver := oauthorizer.NewBrowserSafeRequestInfoResolver(
793+
requestContextMapper,
794+
sets.NewString(bootstrappolicy.AuthenticatedGroup),
795+
requestInfoFactory,
796+
)
797+
personalSARRequestInfoResolver := oauthorizer.NewPersonalSARRequestInfoResolver(browserSafeRequestInfoResolver)
798+
projectRequestInfoResolver := oauthorizer.NewProjectRequestInfoResolver(personalSARRequestInfoResolver)
799+
800+
return projectRequestInfoResolver
801+
}

pkg/cmd/server/kubernetes/master/master_config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var expectedGroupPreferredVersions []string = []string{
3535
"admissionregistration.k8s.io/v1alpha1",
3636
"apps/v1beta1,authentication.k8s.io/v1",
3737
"authorization.k8s.io/v1",
38+
"authorization.openshift.io/v1",
3839
"autoscaling/v1",
3940
"batch/v1",
4041
"certificates.k8s.io/v1beta1",

pkg/cmd/server/origin/controller/standalone_apiserver.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
authzwebhook "k8s.io/apiserver/plugin/pkg/authorizer/webhook"
2020
clientgoclientset "k8s.io/client-go/kubernetes"
2121

22-
"github.com/openshift/origin/pkg/authorization/authorizer"
2322
configapi "github.com/openshift/origin/pkg/cmd/server/api"
2423
serverauthenticator "github.com/openshift/origin/pkg/cmd/server/authenticator"
2524
"github.com/openshift/origin/pkg/cmd/server/crypto"
@@ -57,11 +56,10 @@ func RunControllerServer(servingInfo configapi.HTTPServingInfo, kubeExternal cli
5756
requestInfoResolver := apiserver.NewRequestInfoResolver(&apiserver.Config{})
5857
// the request context mapper for controllers is always separate
5958
requestContextMapper := apirequest.NewRequestContextMapper()
60-
authorizationAttributeBuilder := authorizer.NewAuthorizationAttributeBuilder(requestContextMapper, requestInfoResolver)
6159

6260
// we use direct bypass to allow readiness and health to work regardless of the master health
6361
authz := serverhandlers.NewBypassAuthorizer(remoteAuthz, "/healthz", "/healthz/ready")
64-
handler := serverhandlers.AuthorizationFilter(mux, authz, authorizationAttributeBuilder, requestContextMapper)
62+
handler := apifilters.WithAuthorization(mux, requestContextMapper, authz)
6563
handler = apifilters.WithAuthentication(handler, requestContextMapper, authn, apifilters.Unauthorized(false))
6664
handler = apiserverfilters.WithPanicRecovery(handler)
6765
handler = apifilters.WithRequestInfo(handler, requestInfoResolver, requestContextMapper)

pkg/cmd/server/origin/master.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func (c *MasterConfig) buildHandlerChain() (func(apiHandler http.Handler, kc *ap
287287

288288
// these are all equivalent to the kube handler chain
289289
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
290-
handler = serverhandlers.AuthorizationFilter(handler, c.Authorizer, c.AuthorizationAttributeBuilder, genericConfig.RequestContextMapper)
290+
handler = apifilters.WithAuthorization(handler, c.RequestContextMapper, c.Authorizer)
291291
handler = serverhandlers.ImpersonationFilter(handler, c.Authorizer, cache.NewGroupCache(c.UserInformers.User().InternalVersion().Groups()), genericConfig.RequestContextMapper)
292292
// audit handler must comes before the impersonationFilter to read the original user
293293
if c.Options.AuditConfig.Enabled {
@@ -318,7 +318,7 @@ func (c *MasterConfig) buildHandlerChain() (func(apiHandler http.Handler, kc *ap
318318
// execution - updates vs reads, long reads vs short reads, fat reads vs skinny reads.
319319
// NOTE: read vs. write is implemented in Kube 1.6+
320320
handler = apiserverfilters.WithMaxInFlightLimit(handler, genericConfig.MaxRequestsInFlight, genericConfig.MaxMutatingRequestsInFlight, genericConfig.RequestContextMapper, genericConfig.LongRunningFunc)
321-
handler = apifilters.WithRequestInfo(handler, apiserver.NewRequestInfoResolver(genericConfig), genericConfig.RequestContextMapper)
321+
handler = apifilters.WithRequestInfo(handler, genericConfig.RequestInfoResolver, genericConfig.RequestContextMapper)
322322
handler = apirequest.WithRequestContext(handler, genericConfig.RequestContextMapper)
323323
handler = apiserverfilters.WithPanicRecovery(handler)
324324
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

pkg/cmd/server/origin/master_config.go

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,6 @@ type MasterConfig struct {
100100
Authorizer kauthorizer.Authorizer
101101
SubjectLocator authorizer.SubjectLocator
102102

103-
// TODO(sttts): replace AuthorizationAttributeBuilder with apiserverfilters.NewRequestAttributeGetter
104-
AuthorizationAttributeBuilder authorizer.AuthorizationAttributeBuilder
105-
106103
ProjectAuthorizationCache *projectauth.AuthorizationCache
107104
ProjectCache *projectcache.ProjectCache
108105
ClusterQuotaMappingController *clusterquotamapping.ClusterQuotaMappingController
@@ -300,11 +297,10 @@ func BuildMasterConfig(options configapi.MasterConfig, informers InformerAccess)
300297

301298
RESTOptionsGetter: restOptsGetter,
302299

303-
RuleResolver: ruleResolver,
304-
Authenticator: authenticator,
305-
Authorizer: authorizer,
306-
SubjectLocator: subjectLocator,
307-
AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper),
300+
RuleResolver: ruleResolver,
301+
Authenticator: authenticator,
302+
Authorizer: authorizer,
303+
SubjectLocator: subjectLocator,
308304

309305
ProjectAuthorizationCache: newProjectAuthorizationCache(
310306
subjectLocator,
@@ -782,22 +778,6 @@ func newAuthorizer(kubeAuthorizer kauthorizer.Authorizer, kubeSubjectLocator rba
782778
return authorizer, subjectLocator
783779
}
784780

785-
func newAuthorizationAttributeBuilder(requestContextMapper apirequest.RequestContextMapper) authorizer.AuthorizationAttributeBuilder {
786-
// Default API request info factory
787-
requestInfoFactory := &apirequest.RequestInfoFactory{APIPrefixes: sets.NewString("api", "osapi", "oapi", "apis"), GrouplessAPIPrefixes: sets.NewString("api", "osapi", "oapi")}
788-
// Wrap with a request info factory that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately
789-
browserSafeRequestInfoResolver := authorizer.NewBrowserSafeRequestInfoResolver(
790-
requestContextMapper,
791-
sets.NewString(bootstrappolicy.AuthenticatedGroup),
792-
requestInfoFactory,
793-
)
794-
personalSARRequestInfoResolver := authorizer.NewPersonalSARRequestInfoResolver(browserSafeRequestInfoResolver)
795-
projectRequestInfoResolver := authorizer.NewProjectRequestInfoResolver(personalSARRequestInfoResolver)
796-
797-
authorizationAttributeBuilder := authorizer.NewAuthorizationAttributeBuilder(requestContextMapper, projectRequestInfoResolver)
798-
return authorizationAttributeBuilder
799-
}
800-
801781
// KubeClientsetInternal returns the kubernetes client object
802782
func (c *MasterConfig) KubeClientsetInternal() kclientsetinternal.Interface {
803783
return c.PrivilegedLoopbackKubernetesClientsetInternal

test/cmd/authentication.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ os::cmd::expect_success_and_text "oc get user/~ --token='${allescalatingpowersto
6969
os::cmd::expect_success "oc get secrets --token='${allescalatingpowerstoken}' -n '${project}'"
7070
# scopes allow it, but authorization doesn't
7171
os::cmd::try_until_failure "oc get secrets --token='${allescalatingpowerstoken}' -n default"
72-
os::cmd::expect_failure_and_text "oc get secrets --token='${allescalatingpowerstoken}' -n default" 'cannot list secrets in project'
72+
os::cmd::expect_failure_and_text "oc get secrets --token='${allescalatingpowerstoken}' -n default" 'cannot list secrets in the namespace'
7373
os::cmd::expect_success_and_text "oc get projects --token='${allescalatingpowerstoken}'" "${project}"
7474
os::cmd::expect_success_and_text "oc policy can-i --list --token='${allescalatingpowerstoken}' -n '${project}'" 'get.*pods'
7575

test/cmd/status.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ os::cmd::expect_success_and_text "oc login --server=${KUBERNETES_MASTER} --certi
4444
os::cmd::expect_success_and_text 'oc status' "You don't have any projects. You can try to create a new project, by running"
4545
os::cmd::expect_success_and_text 'oc status --all-namespaces' "Showing all projects on server"
4646
# make sure `oc status` does not re-use the "no projects" message from `oc login` if -n is specified
47-
os::cmd::expect_failure_and_text 'oc status -n forbidden' 'Error from server \(Forbidden\): User "test-user" cannot get project "forbidden"'
47+
os::cmd::expect_failure_and_text 'oc status -n forbidden' 'Error from server \(Forbidden\): User "test-user" cannot get projects in the namespace "forbidden"'
4848

4949
# create a new project
5050
os::cmd::expect_success "oc new-project project-bar --display-name='my project' --description='test project'"
5151
os::cmd::expect_success_and_text "oc project" 'Using project "project-bar"'
5252

5353
# make sure `oc status` does not use "no projects" message if there is a project created
5454
os::cmd::expect_success_and_text 'oc status' "In project my project \(project-bar\) on server"
55-
os::cmd::expect_failure_and_text 'oc status -n forbidden' 'Error from server \(Forbidden\): User "test-user" cannot get project "forbidden"'
55+
os::cmd::expect_failure_and_text 'oc status -n forbidden' 'Error from server \(Forbidden\): User "test-user" cannot get projects in the namespace "forbidden"'
5656

5757
# create a second project
5858
os::cmd::expect_success "oc new-project project-bar-2 --display-name='my project 2' --description='test project 2'"
@@ -62,7 +62,7 @@ os::cmd::expect_success_and_text "oc project" 'Using project "project-bar-2"'
6262
# message since `project-bar` still exists
6363
os::cmd::expect_success_and_text "oc delete project project-bar-2" 'project "project-bar-2" deleted'
6464
# the deletion is asynchronous and can take a while, so wait until we see the error
65-
os::cmd::try_until_text "oc status" 'Error from server \(Forbidden\): User "test-user" cannot get project "project-bar-2"'
65+
os::cmd::try_until_text "oc status" 'Error from server \(Forbidden\): User "test-user" cannot get projects in the namespace "project-bar-2"'
6666

6767
# delete "project-bar" and test that `oc status` still does not return the "no projects" message.
6868
# Although we are deleting the last remaining project, the current context's namespace is still set
@@ -71,7 +71,7 @@ os::cmd::try_until_text "oc status" 'Error from server \(Forbidden\): User "test
7171
os::cmd::expect_success "oc project project-bar"
7272
os::cmd::expect_success "oc delete project project-bar"
7373
# the deletion is asynchronous and can take a while, so wait until we see the error
74-
os::cmd::try_until_text "oc status" 'Error from server \(Forbidden\): User "test-user" cannot get project "project-bar"'
74+
os::cmd::try_until_text "oc status" 'Error from server \(Forbidden\): User "test-user" cannot get projects in the namespace "project-bar"'
7575
os::cmd::try_until_not_text "oc get projects" "project-bar"
7676
os::cmd::try_until_not_text "oc get projects" "project-bar-2"
7777
os::cmd::expect_success "oc logout"

0 commit comments

Comments
 (0)