forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
authorizer.go
106 lines (87 loc) · 2.8 KB
/
authorizer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package browsersafe
import (
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authorization/authorizer"
)
const (
proxyAction = "proxy"
unsafeProxy = "unsafeproxy"
)
type browserSafeAuthorizer struct {
delegate authorizer.Authorizer
// list of groups, any of which indicate the request is authenticated
authenticatedGroups sets.String
}
func NewBrowserSafeAuthorizer(delegate authorizer.Authorizer, authenticatedGroups ...string) authorizer.Authorizer {
return &browserSafeAuthorizer{
delegate: delegate,
authenticatedGroups: sets.NewString(authenticatedGroups...),
}
}
func (a *browserSafeAuthorizer) Authorize(attributes authorizer.Attributes) (authorizer.Decision, string, error) {
attrs := a.getBrowserSafeAttributes(attributes)
decision, reason, err := a.delegate.Authorize(attrs)
safeAttributes, changed := attrs.(*browserSafeAttributes)
// check if the request was not allowed and we changed the attributes
if decision == authorizer.DecisionAllow || !changed {
return decision, reason, err
}
// if so, use this information to update the reason
return decision, safeAttributes.reason(reason), err
}
func (a *browserSafeAuthorizer) getBrowserSafeAttributes(attributes authorizer.Attributes) authorizer.Attributes {
if !attributes.IsResourceRequest() {
return attributes
}
isProxyVerb := attributes.GetVerb() == proxyAction
isProxySubresource := attributes.GetSubresource() == proxyAction
if !isProxyVerb && !isProxySubresource {
// Requests to non-proxy resources don't expose HTML or HTTP-handling user content to browsers
return attributes
}
if user := attributes.GetUser(); user != nil {
if a.authenticatedGroups.HasAny(user.GetGroups()...) {
// An authenticated request indicates this isn't a browser page load.
// Browsers cannot make direct authenticated requests.
// This depends on the API not enabling basic or cookie-based auth.
return attributes
}
}
return &browserSafeAttributes{
Attributes: attributes,
isProxyVerb: isProxyVerb,
isProxySubresource: isProxySubresource,
}
}
type browserSafeAttributes struct {
authorizer.Attributes
isProxyVerb, isProxySubresource bool
}
func (b *browserSafeAttributes) GetVerb() string {
if b.isProxyVerb {
return unsafeProxy
}
return b.Attributes.GetVerb()
}
func (b *browserSafeAttributes) GetSubresource() string {
if b.isProxySubresource {
return unsafeProxy
}
return b.Attributes.GetSubresource()
}
func (b *browserSafeAttributes) reason(reason string) string {
if b.isProxyVerb {
if len(reason) != 0 {
reason += ", "
}
reason += fmt.Sprintf("%s verb changed to %s", proxyAction, unsafeProxy)
}
if b.isProxySubresource {
if len(reason) != 0 {
reason += ", "
}
reason += fmt.Sprintf("%s subresource changed to %s", proxyAction, unsafeProxy)
}
return reason
}