Exemplo n.º 1
0
// WithAuthorizationCheck passes all authorized requests on to handler, and returns a forbidden error otherwise.
func WithAuthorization(handler http.Handler, requestContextMapper request.RequestContextMapper, a authorizer.Authorizer) http.Handler {
	if a == nil {
		glog.Warningf("Authorization is disabled")
		return handler
	}
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		ctx, ok := requestContextMapper.Get(req)
		if !ok {
			responsewriters.InternalError(w, req, errors.New("no context found for request"))
			return
		}

		attributes, err := GetAuthorizerAttributes(ctx)
		if err != nil {
			responsewriters.InternalError(w, req, err)
			return
		}
		authorized, reason, err := a.Authorize(attributes)
		if authorized {
			handler.ServeHTTP(w, req)
			return
		}
		if err != nil {
			responsewriters.InternalError(w, req, err)
			return
		}

		glog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason)
		responsewriters.Forbidden(attributes, w, req, reason)
	})
}
Exemplo n.º 2
0
// authorizedForPolicy returns true if info is authorized to perform a "get" on policy.
func authorizedForPolicy(info user.Info, policy *extensions.PodSecurityPolicy, authz authorizer.Authorizer) bool {
	// if no info exists then the API is being hit via the unsecured port.  In this case
	// authorize the request.
	if info == nil {
		return true
	}
	attr := buildAttributes(info, policy)
	allowed, _, _ := authz.Authorize(attr)
	return allowed
}
Exemplo n.º 3
0
// BindingAuthorized returns true if the user associated with the context is explicitly authorized to bind the specified roleRef
func BindingAuthorized(ctx genericapirequest.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool {
	if a == nil {
		return false
	}

	user, ok := genericapirequest.UserFrom(ctx)
	if !ok {
		return false
	}

	attrs := authorizer.AttributesRecord{
		User: user,
		Verb: "bind",
		// check against the namespace where the binding is being created (or the empty namespace for clusterrolebindings).
		// this allows delegation to bind particular clusterroles in rolebindings within particular namespaces,
		// and to authorize binding a clusterrole across all namespaces in a clusterrolebinding.
		Namespace:       bindingNamespace,
		ResourceRequest: true,
	}

	// This occurs after defaulting and conversion, so values pulled from the roleRef won't change
	// Invalid APIGroup or Name values will fail validation
	switch roleRef.Kind {
	case "ClusterRole":
		attrs.APIGroup = roleRef.APIGroup
		attrs.Resource = "clusterroles"
		attrs.Name = roleRef.Name
	case "Role":
		attrs.APIGroup = roleRef.APIGroup
		attrs.Resource = "roles"
		attrs.Name = roleRef.Name
	default:
		return false
	}

	ok, _, err := a.Authorize(attrs)
	if err != nil {
		utilruntime.HandleError(fmt.Errorf(
			"error authorizing user %#v to bind %#v in namespace %s: %v",
			roleRef, bindingNamespace, user, err,
		))
	}
	return ok
}
Exemplo n.º 4
0
// WithImpersonation is a filter that will inspect and check requests that attempt to change the user.Info for their requests
func WithImpersonation(handler http.Handler, requestContextMapper request.RequestContextMapper, a authorizer.Authorizer) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		impersonationRequests, err := buildImpersonationRequests(req.Header)
		if err != nil {
			glog.V(4).Infof("%v", err)
			responsewriters.InternalError(w, req, err)
			return
		}
		if len(impersonationRequests) == 0 {
			handler.ServeHTTP(w, req)
			return
		}

		ctx, exists := requestContextMapper.Get(req)
		if !exists {
			responsewriters.InternalError(w, req, errors.New("no context found for request"))
			return
		}
		requestor, exists := request.UserFrom(ctx)
		if !exists {
			responsewriters.InternalError(w, req, errors.New("no user found for request"))
			return
		}

		// if groups are not specified, then we need to look them up differently depending on the type of user
		// if they are specified, then they are the authority
		groupsSpecified := len(req.Header[authenticationapi.ImpersonateGroupHeader]) > 0

		// make sure we're allowed to impersonate each thing we're requesting.  While we're iterating through, start building username
		// and group information
		username := ""
		groups := []string{}
		userExtra := map[string][]string{}
		for _, impersonationRequest := range impersonationRequests {
			actingAsAttributes := &authorizer.AttributesRecord{
				User:            requestor,
				Verb:            "impersonate",
				APIGroup:        impersonationRequest.GetObjectKind().GroupVersionKind().Group,
				Namespace:       impersonationRequest.Namespace,
				Name:            impersonationRequest.Name,
				ResourceRequest: true,
			}

			switch impersonationRequest.GetObjectKind().GroupVersionKind().GroupKind() {
			case api.Kind("ServiceAccount"):
				actingAsAttributes.Resource = "serviceaccounts"
				username = serviceaccount.MakeUsername(impersonationRequest.Namespace, impersonationRequest.Name)
				if !groupsSpecified {
					// if groups aren't specified for a service account, we know the groups because its a fixed mapping.  Add them
					groups = serviceaccount.MakeGroupNames(impersonationRequest.Namespace, impersonationRequest.Name)
				}

			case api.Kind("User"):
				actingAsAttributes.Resource = "users"
				username = impersonationRequest.Name

			case api.Kind("Group"):
				actingAsAttributes.Resource = "groups"
				groups = append(groups, impersonationRequest.Name)

			case authenticationapi.Kind("UserExtra"):
				extraKey := impersonationRequest.FieldPath
				extraValue := impersonationRequest.Name
				actingAsAttributes.Resource = "userextras"
				actingAsAttributes.Subresource = extraKey
				userExtra[extraKey] = append(userExtra[extraKey], extraValue)

			default:
				glog.V(4).Infof("unknown impersonation request type: %v", impersonationRequest)
				responsewriters.Forbidden(actingAsAttributes, w, req, fmt.Sprintf("unknown impersonation request type: %v", impersonationRequest))
				return
			}

			allowed, reason, err := a.Authorize(actingAsAttributes)
			if err != nil || !allowed {
				glog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err)
				responsewriters.Forbidden(actingAsAttributes, w, req, reason)
				return
			}
		}

		newUser := &user.DefaultInfo{
			Name:   username,
			Groups: groups,
			Extra:  userExtra,
		}
		requestContextMapper.Update(req, request.WithUser(ctx, newUser))

		oldUser, _ := request.UserFrom(ctx)
		httplog.LogOf(req, w).Addf("%v is acting as %v", oldUser, newUser)

		// clear all the impersonation headers from the request
		req.Header.Del(authenticationapi.ImpersonateUserHeader)
		req.Header.Del(authenticationapi.ImpersonateGroupHeader)
		for headerName := range req.Header {
			if strings.HasPrefix(headerName, authenticationapi.ImpersonateUserExtraHeaderPrefix) {
				req.Header.Del(headerName)
			}
		}

		handler.ServeHTTP(w, req)
	})
}