@@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- package framework
17
+ package auth
18
18
19
19
import (
20
- "k8s.io/klog "
20
+ "fmt "
21
21
"sync"
22
22
"time"
23
23
24
+ "github.com/onsi/ginkgo"
25
+ "github.com/pkg/errors"
24
26
authorizationv1beta1 "k8s.io/api/authorization/v1beta1"
25
27
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
26
28
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -36,6 +38,12 @@ const (
36
38
policyCachePollTimeout = 5 * time .Second
37
39
)
38
40
41
+ type bindingsGetter interface {
42
+ v1beta1rbac.RoleBindingsGetter
43
+ v1beta1rbac.ClusterRoleBindingsGetter
44
+ v1beta1rbac.ClusterRolesGetter
45
+ }
46
+
39
47
// WaitForAuthorizationUpdate checks if the given user can perform the named verb and action.
40
48
// If policyCachePollTimeout is reached without the expected condition matching, an error is returned
41
49
func WaitForAuthorizationUpdate (c v1beta1authorization.SubjectAccessReviewsGetter , user , namespace , verb string , resource schema.GroupResource , allowed bool ) error {
@@ -57,12 +65,15 @@ func WaitForNamedAuthorizationUpdate(c v1beta1authorization.SubjectAccessReviews
57
65
User : user ,
58
66
},
59
67
}
68
+
60
69
err := wait .Poll (policyCachePollInterval , policyCachePollTimeout , func () (bool , error ) {
61
70
response , err := c .SubjectAccessReviews ().Create (review )
62
71
// GKE doesn't enable the SAR endpoint. Without this endpoint, we cannot determine if the policy engine
63
72
// has adjusted as expected. In this case, simply wait one second and hope it's up to date
73
+ // TODO: Should have a check for the provider here but that introduces too tight of
74
+ // coupling with the `framework` package. See: https://github.com/kubernetes/kubernetes/issues/76726
64
75
if apierrors .IsNotFound (err ) {
65
- klog . Info ("SubjectAccessReview endpoint is missing" )
76
+ logf ("SubjectAccessReview endpoint is missing" )
66
77
time .Sleep (1 * time .Second )
67
78
return true , nil
68
79
}
@@ -77,8 +88,13 @@ func WaitForNamedAuthorizationUpdate(c v1beta1authorization.SubjectAccessReviews
77
88
return err
78
89
}
79
90
80
- // BindClusterRole binds the cluster role at the cluster scope
81
- func BindClusterRole (c v1beta1rbac.ClusterRoleBindingsGetter , clusterRole , ns string , subjects ... rbacv1beta1.Subject ) {
91
+ // BindClusterRole binds the cluster role at the cluster scope. If RBAC is not enabled, nil
92
+ // is returned with no action.
93
+ func BindClusterRole (c bindingsGetter , clusterRole , ns string , subjects ... rbacv1beta1.Subject ) error {
94
+ if ! IsRBACEnabled (c ) {
95
+ return nil
96
+ }
97
+
82
98
// Since the namespace names are unique, we can leave this lying around so we don't have to race any caches
83
99
_ , err := c .ClusterRoleBindings ().Create (& rbacv1beta1.ClusterRoleBinding {
84
100
ObjectMeta : metav1.ObjectMeta {
@@ -92,23 +108,30 @@ func BindClusterRole(c v1beta1rbac.ClusterRoleBindingsGetter, clusterRole, ns st
92
108
Subjects : subjects ,
93
109
})
94
110
95
- // if we failed, don't fail the entire test because it may still work. RBAC may simply be disabled.
96
111
if err != nil {
97
- klog . Errorf ( "Error binding clusterrole/%s for %q for %v\n " , clusterRole , ns , subjects )
112
+ return errors . Wrapf ( err , " binding clusterrole/%s for %q for %v" , clusterRole , ns , subjects )
98
113
}
114
+
115
+ return nil
99
116
}
100
117
101
- // BindClusterRoleInNamespace binds the cluster role at the namespace scope
102
- func BindClusterRoleInNamespace (c v1beta1rbac.RoleBindingsGetter , clusterRole , ns string , subjects ... rbacv1beta1.Subject ) {
103
- bindInNamespace (c , "ClusterRole" , clusterRole , ns , subjects ... )
118
+ // BindClusterRoleInNamespace binds the cluster role at the namespace scope. If RBAC is not enabled, nil
119
+ // is returned with no action.
120
+ func BindClusterRoleInNamespace (c bindingsGetter , clusterRole , ns string , subjects ... rbacv1beta1.Subject ) error {
121
+ return bindInNamespace (c , "ClusterRole" , clusterRole , ns , subjects ... )
104
122
}
105
123
106
- // BindRoleInNamespace binds the role at the namespace scope
107
- func BindRoleInNamespace (c v1beta1rbac.RoleBindingsGetter , role , ns string , subjects ... rbacv1beta1.Subject ) {
108
- bindInNamespace (c , "Role" , role , ns , subjects ... )
124
+ // BindRoleInNamespace binds the role at the namespace scope. If RBAC is not enabled, nil
125
+ // is returned with no action.
126
+ func BindRoleInNamespace (c bindingsGetter , role , ns string , subjects ... rbacv1beta1.Subject ) error {
127
+ return bindInNamespace (c , "Role" , role , ns , subjects ... )
109
128
}
110
129
111
- func bindInNamespace (c v1beta1rbac.RoleBindingsGetter , roleType , role , ns string , subjects ... rbacv1beta1.Subject ) {
130
+ func bindInNamespace (c bindingsGetter , roleType , role , ns string , subjects ... rbacv1beta1.Subject ) error {
131
+ if ! IsRBACEnabled (c ) {
132
+ return nil
133
+ }
134
+
112
135
// Since the namespace names are unique, we can leave this lying around so we don't have to race any caches
113
136
_ , err := c .RoleBindings (ns ).Create (& rbacv1beta1.RoleBinding {
114
137
ObjectMeta : metav1.ObjectMeta {
@@ -122,10 +145,11 @@ func bindInNamespace(c v1beta1rbac.RoleBindingsGetter, roleType, role, ns string
122
145
Subjects : subjects ,
123
146
})
124
147
125
- // if we failed, don't fail the entire test because it may still work. RBAC may simply be disabled.
126
148
if err != nil {
127
- klog . Errorf ( "Error binding %s/%s into %q for %v\n " , roleType , role , ns , subjects )
149
+ return errors . Wrapf ( err , " binding %s/%s into %q for %v" , roleType , role , ns , subjects )
128
150
}
151
+
152
+ return nil
129
153
}
130
154
131
155
var (
@@ -134,19 +158,41 @@ var (
134
158
)
135
159
136
160
// IsRBACEnabled returns true if RBAC is enabled. Otherwise false.
137
- func IsRBACEnabled (f * Framework ) bool {
161
+ func IsRBACEnabled (crGetter v1beta1rbac. ClusterRolesGetter ) bool {
138
162
isRBACEnabledOnce .Do (func () {
139
- crs , err := f . ClientSet . RbacV1 () .ClusterRoles ().List (metav1.ListOptions {})
163
+ crs , err := crGetter .ClusterRoles ().List (metav1.ListOptions {})
140
164
if err != nil {
141
- Logf ("Error listing ClusterRoles; assuming RBAC is disabled: %v" , err )
165
+ logf ("Error listing ClusterRoles; assuming RBAC is disabled: %v" , err )
142
166
isRBACEnabled = false
143
167
} else if crs == nil || len (crs .Items ) == 0 {
144
- Logf ("No ClusterRoles found; assuming RBAC is disabled." )
168
+ logf ("No ClusterRoles found; assuming RBAC is disabled." )
145
169
isRBACEnabled = false
146
170
} else {
147
- Logf ("Found ClusterRoles; assuming RBAC is enabled." )
171
+ logf ("Found ClusterRoles; assuming RBAC is enabled." )
148
172
isRBACEnabled = true
149
173
}
150
174
})
175
+
151
176
return isRBACEnabled
152
177
}
178
+
179
+ // logf logs INFO lines to the GinkgoWriter.
180
+ // TODO: Log functions like these should be put into their own package,
181
+ // see: https://github.com/kubernetes/kubernetes/issues/76728
182
+ func logf (format string , args ... interface {}) {
183
+ log ("INFO" , format , args ... )
184
+ }
185
+
186
+ // log prints formatted log messages to the global GinkgoWriter.
187
+ // TODO: Log functions like these should be put into their own package,
188
+ // see: https://github.com/kubernetes/kubernetes/issues/76728
189
+ func log (level string , format string , args ... interface {}) {
190
+ fmt .Fprintf (ginkgo .GinkgoWriter , nowStamp ()+ ": " + level + ": " + format + "\n " , args ... )
191
+ }
192
+
193
+ // nowStamp returns the current time formatted for placement in the logs (time.StampMilli).
194
+ // TODO: If only used for logging, this should be put into a logging package,
195
+ // see: https://github.com/kubernetes/kubernetes/issues/76728
196
+ func nowStamp () string {
197
+ return time .Now ().Format (time .StampMilli )
198
+ }
0 commit comments