Example #1
0
// NewRequestAuthenticator creates an http handler that tries to authenticate the given request as a user, and then
// stores any such user found onto the provided context for the request. If authentication fails or returns an error
// the failed handler is used. On success, handler is invoked to serve the request.
func NewRequestAuthenticator(mapper api.RequestContextMapper, auth authenticator.Request, failed http.Handler, handler http.Handler) (http.Handler, error) {
	return api.NewRequestContextFilter(
		mapper,
		http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			user, ok, err := auth.AuthenticateRequest(req)
			if err != nil || !ok {
				if err != nil {
					glog.Errorf("Unable to authenticate the request due to an error: %v", err)
				}
				failed.ServeHTTP(w, req)
				return
			}

			if ctx, ok := mapper.Get(req); ok {
				mapper.Update(req, api.WithUser(ctx, user))
			}

			authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc()

			handler.ServeHTTP(w, req)
		}),
	)
}
Example #2
0
func WithImpersonation(handler http.Handler, requestContextMapper api.RequestContextMapper, a authorizer.Authorizer) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		requestedSubject := req.Header.Get("Impersonate-User")
		if len(requestedSubject) == 0 {
			handler.ServeHTTP(w, req)
			return
		}

		ctx, exists := requestContextMapper.Get(req)
		if !exists {
			forbidden(w, req)
			return
		}
		requestor, exists := api.UserFrom(ctx)
		if !exists {
			forbidden(w, req)
			return
		}

		actingAsAttributes := &authorizer.AttributesRecord{
			User:            requestor,
			Verb:            "impersonate",
			APIGroup:        api.GroupName,
			Resource:        "users",
			Name:            requestedSubject,
			ResourceRequest: true,
		}
		if namespace, name, err := serviceaccount.SplitUsername(requestedSubject); err == nil {
			actingAsAttributes.Resource = "serviceaccounts"
			actingAsAttributes.Namespace = namespace
			actingAsAttributes.Name = name
		}

		err := a.Authorize(actingAsAttributes)
		if err != nil {
			forbidden(w, req)
			return
		}

		switch {
		case strings.HasPrefix(requestedSubject, serviceaccount.ServiceAccountUsernamePrefix):
			namespace, name, err := serviceaccount.SplitUsername(requestedSubject)
			if err != nil {
				forbidden(w, req)
				return
			}
			requestContextMapper.Update(req, api.WithUser(ctx, serviceaccount.UserInfo(namespace, name, "")))

		default:
			newUser := &user.DefaultInfo{
				Name: requestedSubject,
			}
			requestContextMapper.Update(req, api.WithUser(ctx, newUser))
		}

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

		handler.ServeHTTP(w, req)
	})
}