| ... | ... |
@@ -174,6 +174,11 @@ type ResourceAccessReviewResponse struct {
|
| 174 | 174 |
Users sets.String |
| 175 | 175 |
// Groups is the list of groups who can perform the action |
| 176 | 176 |
Groups sets.String |
| 177 |
+ |
|
| 178 |
+ // EvaluationError is an indication that some error occurred during resolution, but partial results can still be returned. |
|
| 179 |
+ // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. This is |
|
| 180 |
+ // most common when a bound role is missing, but enough roles are still present and bound to reason about the request. |
|
| 181 |
+ EvaluationError string |
|
| 177 | 182 |
} |
| 178 | 183 |
|
| 179 | 184 |
// ResourceAccessReview is a means to request a list of which users and groups are authorized to perform the |
| ... | ... |
@@ -239,10 +239,11 @@ func (ResourceAccessReview) SwaggerDoc() map[string]string {
|
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 | 241 |
var map_ResourceAccessReviewResponse = map[string]string{
|
| 242 |
- "": "ResourceAccessReviewResponse describes who can perform the action", |
|
| 243 |
- "namespace": "Namespace is the namespace used for the access review", |
|
| 244 |
- "users": "UsersSlice is the list of users who can perform the action", |
|
| 245 |
- "groups": "GroupsSlice is the list of groups who can perform the action", |
|
| 242 |
+ "": "ResourceAccessReviewResponse describes who can perform the action", |
|
| 243 |
+ "namespace": "Namespace is the namespace used for the access review", |
|
| 244 |
+ "users": "UsersSlice is the list of users who can perform the action", |
|
| 245 |
+ "groups": "GroupsSlice is the list of groups who can perform the action", |
|
| 246 |
+ "evalutionError": "EvaluationError is an indication that some error occurred during resolution, but partial results can still be returned. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. This is most common when a bound role is missing, but enough roles are still present and bound to reason about the request.", |
|
| 246 | 247 |
} |
| 247 | 248 |
|
| 248 | 249 |
func (ResourceAccessReviewResponse) SwaggerDoc() map[string]string {
|
| ... | ... |
@@ -155,6 +155,11 @@ type ResourceAccessReviewResponse struct {
|
| 155 | 155 |
UsersSlice []string `json:"users"` |
| 156 | 156 |
// GroupsSlice is the list of groups who can perform the action |
| 157 | 157 |
GroupsSlice []string `json:"groups"` |
| 158 |
+ |
|
| 159 |
+ // EvaluationError is an indication that some error occurred during resolution, but partial results can still be returned. |
|
| 160 |
+ // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. This is |
|
| 161 |
+ // most common when a bound role is missing, but enough roles are still present and bound to reason about the request. |
|
| 162 |
+ EvaluationError string `json:"evalutionError"` |
|
| 158 | 163 |
} |
| 159 | 164 |
|
| 160 | 165 |
// ResourceAccessReview is a means to request a list of which users and groups are authorized to perform the |
| ... | ... |
@@ -51,13 +51,16 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err |
| 51 | 51 |
|
| 52 | 52 |
requestContext := kapi.WithNamespace(ctx, resourceAccessReview.Action.Namespace) |
| 53 | 53 |
attributes := authorizer.ToDefaultAuthorizationAttributes(resourceAccessReview.Action) |
| 54 |
- users, groups, _ := r.authorizer.GetAllowedSubjects(requestContext, attributes) |
|
| 54 |
+ users, groups, err := r.authorizer.GetAllowedSubjects(requestContext, attributes) |
|
| 55 | 55 |
|
| 56 | 56 |
response := &authorizationapi.ResourceAccessReviewResponse{
|
| 57 | 57 |
Namespace: resourceAccessReview.Action.Namespace, |
| 58 | 58 |
Users: users, |
| 59 | 59 |
Groups: groups, |
| 60 | 60 |
} |
| 61 |
+ if err != nil {
|
|
| 62 |
+ response.EvaluationError = err.Error() |
|
| 63 |
+ } |
|
| 61 | 64 |
|
| 62 | 65 |
return response, nil |
| 63 | 66 |
} |
| ... | ... |
@@ -138,5 +138,9 @@ func (o *whoCanOptions) run() error {
|
| 138 | 138 |
fmt.Printf("Groups: %s\n\n", strings.Join(resourceAccessReviewResponse.Groups.List(), "\n "))
|
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 |
+ if len(resourceAccessReviewResponse.EvaluationError) != 0 {
|
|
| 142 |
+ fmt.Printf("Error during evaluation, results may not be complete: %s\n", resourceAccessReviewResponse.EvaluationError)
|
|
| 143 |
+ } |
|
| 144 |
+ |
|
| 141 | 145 |
return nil |
| 142 | 146 |
} |
| ... | ... |
@@ -304,7 +304,10 @@ func (test resourceAccessReviewTest) run(t *testing.T) {
|
| 304 | 304 |
} |
| 305 | 305 |
} |
| 306 | 306 |
|
| 307 |
- if actualResponse.Namespace != test.response.Namespace || !reflect.DeepEqual(actualResponse.Users.List(), test.response.Users.List()) || !reflect.DeepEqual(actualResponse.Groups.List(), test.response.Groups.List()) {
|
|
| 307 |
+ if actualResponse.Namespace != test.response.Namespace || |
|
| 308 |
+ !reflect.DeepEqual(actualResponse.Users.List(), test.response.Users.List()) || |
|
| 309 |
+ !reflect.DeepEqual(actualResponse.Groups.List(), test.response.Groups.List()) || |
|
| 310 |
+ actualResponse.EvaluationError != test.response.EvaluationError {
|
|
| 308 | 311 |
failMessage = fmt.Sprintf("%s: %#v: expected %#v, got %#v", test.description, test.review, test.response, actualResponse)
|
| 309 | 312 |
return false, nil |
| 310 | 313 |
} |
| ... | ... |
@@ -354,7 +357,10 @@ func (test localResourceAccessReviewTest) run(t *testing.T) {
|
| 354 | 354 |
} |
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 |
- if actualResponse.Namespace != test.response.Namespace || !reflect.DeepEqual(actualResponse.Users.List(), test.response.Users.List()) || !reflect.DeepEqual(actualResponse.Groups.List(), test.response.Groups.List()) {
|
|
| 357 |
+ if actualResponse.Namespace != test.response.Namespace || |
|
| 358 |
+ !reflect.DeepEqual(actualResponse.Users.List(), test.response.Users.List()) || |
|
| 359 |
+ !reflect.DeepEqual(actualResponse.Groups.List(), test.response.Groups.List()) || |
|
| 360 |
+ actualResponse.EvaluationError != test.response.EvaluationError {
|
|
| 358 | 361 |
failMessage = fmt.Sprintf("%s: %#v: expected %#v, got %#v", test.description, test.review, test.response, actualResponse)
|
| 359 | 362 |
return false, nil |
| 360 | 363 |
} |
| ... | ... |
@@ -495,9 +501,10 @@ func TestAuthorizationResourceAccessReview(t *testing.T) {
|
| 495 | 495 |
clientInterface: clusterAdminClient.LocalResourceAccessReviews("mallet-project"),
|
| 496 | 496 |
review: localRequestWhoCanViewDeploymentConfigs, |
| 497 | 497 |
response: authorizationapi.ResourceAccessReviewResponse{
|
| 498 |
- Users: sets.NewString("edgar"),
|
|
| 499 |
- Groups: sets.NewString(), |
|
| 500 |
- Namespace: "mallet-project", |
|
| 498 |
+ Users: sets.NewString("edgar"),
|
|
| 499 |
+ Groups: sets.NewString(), |
|
| 500 |
+ Namespace: "mallet-project", |
|
| 501 |
+ EvaluationError: `role "admin" not found`, |
|
| 501 | 502 |
}, |
| 502 | 503 |
} |
| 503 | 504 |
test.response.Users.Insert(globalClusterReaderUsers.List()...) |