コード例 #1
0
ファイル: middleware.go プロジェクト: thanzen/hydra
func (m *Middleware) IsAuthorized(resource, permission string, environment *env) func(hydcon.ContextHandler) hydcon.ContextHandler {
	return func(next hydcon.ContextHandler) hydcon.ContextHandler {
		return hydcon.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
			if environment == nil {
				environment = Env(req)
			}

			policies, err := hydcon.PoliciesFromContext(ctx)
			if err != nil {
				log.WithFields(log.Fields{"authorization": "forbidden"}).Warnf(`Policy extraction failed: "%s".`, err)
				errorHandler(rw, req, http.StatusForbidden)
				return
			}

			subject, err := hydcon.SubjectFromContext(ctx)
			if err != nil {
				log.WithFields(log.Fields{"authorization": "forbidden"}).Warnf(`Forbidden! Subject extraction failed: "%s".`, err)
				errorHandler(rw, req, http.StatusForbidden)
				return
			}

			ok, err := guard.IsGranted(resource, permission, subject, policies, environment.Ctx())
			if err != nil || !ok {
				log.WithFields(log.Fields{"authorization": "forbidden"}).Warnf(`Forbidden! Subject "%s" is not being granted access "%s" to resource "%s".`, subject, permission, resource)
				errorHandler(rw, req, http.StatusForbidden)
				return
			}

			log.WithFields(log.Fields{"authorization": "success"}).Infof(`Allowed! Granting subject "%s" access "%s" to resource "%s".`, subject, permission, resource)
			next.ServeHTTPContext(ctx, rw, req)
		})
	}
}
コード例 #2
0
ファイル: guard.go プロジェクト: thanzen/hydra
func (g *Guard) IsGranted(resource, permission, subject string, policies []policy.Policy, ctx *Context) (allowed bool, err error) {
	allowed = false
	// Iterate through all policies
	for _, p := range policies {
		// Does the resource match with one of the policies?
		if rm, err := Matches(p.GetResources(), resource); err != nil {
			log.WithFields(log.Fields{
				"resources": p.GetResources(),
				"resource":  resource,
				"error":     err,
			}).Warn("Could not match resources.")
			return false, err
		} else if !rm {
			continue
		}

		// Does the action match with one of the policies?
		if pm, err := Matches(p.GetPermissions(), permission); err != nil {
			log.WithFields(log.Fields{
				"permissions": p.GetPermissions(),
				"permission":  permission,
				"error":       err,
			}).Warn("Could not match permissions.")
			return false, err
		} else if !pm {
			continue
		}

		// Does the subject match with one of the policies?
		if sm, err := Matches(p.GetSubjects(), subject); err != nil {
			log.WithFields(log.Fields{
				"subjects": p.GetSubjects(),
				"subject":  subject,
				"error":    err,
			}).Warn("Could not match subjects.")
			return false, err
		} else if !sm && len(p.GetSubjects()) > 0 {
			// If no match exists, but the subjects are scoped, this policy is irrelevant
			continue
		}

		if !g.PassesConditions(p, ctx, permission, resource, subject) {
			continue
		}

		// Does the policy enforce a deny policy? If yes, this overrides all allow policies -> access denied.
		if !p.HasAccess() {
			return false, nil
		}
		allowed = true
	}
	return allowed, nil
}
コード例 #3
0
ファイル: handler.go プロジェクト: thanzen/hydra
func (h *Handler) Granted(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
	var p struct {
		Resource   string            `json:"string"`
		Subject    string            `json:"subject"`
		Permission string            `json:"permission"`
		Context    *operator.Context `json:"context"`
	}
	decoder := json.NewDecoder(req.Body)
	if err := decoder.Decode(&p); err != nil {
		http.Error(rw, err.Error(), http.StatusBadRequest)
		return
	}

	policies, err := h.s.FindPoliciesForSubject(p.Subject)
	if err != nil {
		log.WithFields(log.Fields{
			"error":      err.Error(),
			"resource":   p.Resource,
			"permission": p.Permission,
			"subject":    p.Subject,
			"context":    fmt.Sprintf("%s", p.Context),
		})
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	allowed, err := h.g.IsGranted(p.Resource, p.Permission, p.Subject, policies, p.Context)
	if err != nil {
		log.WithFields(log.Fields{
			"error":      err.Error(),
			"resource":   p.Resource,
			"permission": p.Permission,
			"subject":    p.Subject,
			"policies":   fmt.Sprintf("%s", policies),
			"context":    fmt.Sprintf("%s", p.Context),
		})
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	pkg.WriteJSON(rw, struct {
		Allowed bool `json:"allowed"`
	}{Allowed: allowed})
}
コード例 #4
0
ファイル: middleware.go プロジェクト: thanzen/hydra
func (m *Middleware) IsAuthenticated(next hydcon.ContextHandler) hydcon.ContextHandler {
	return hydcon.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
		if !hydcon.IsAuthenticatedFromContext(ctx) {
			log.WithFields(log.Fields{"authentication": "fail"}).Warn(`Not able to get authorization from context.`)
			errorHandler(rw, req, http.StatusUnauthorized)
			return
		}

		subject, err := hydcon.SubjectFromContext(ctx)
		if err != nil {
			log.WithFields(log.Fields{"authentication": "fail"}).Warnf("Subject extraction failed: %s", err)
			errorHandler(rw, req, http.StatusUnauthorized)
			return
		} else if subject == "" {
			log.WithFields(log.Fields{"authentication": "fail"}).Warnf("No subject given.")
			errorHandler(rw, req, http.StatusUnauthorized)
			return
		}

		log.WithFields(log.Fields{"authentication": "success"}).Infof(`Authenticated subject "%s".`, subject)
		next.ServeHTTPContext(ctx, rw, req)
	})
}
コード例 #5
0
ファイル: handler.go プロジェクト: thanzen/hydra
func (h *Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()

	bearer := osin.CheckBearerAuth(r)
	if bearer == nil {
		log.WithField("introspect", "fail").Warn("No authorization header given.")
		http.Error(w, "No bearer given.", http.StatusUnauthorized)
		return
	} else if bearer.Code == "" {
		log.WithField("introspect", "fail").Warn("No authorization bearer is empty.")
		http.Error(w, "No bearer token given.", http.StatusUnauthorized)
		return
	}

	token, err := h.JWT.VerifyToken([]byte(bearer.Code))
	if err != nil {
		log.WithField("introspect", "fail").Warn("Bearer token is invalid.")
		http.Error(w, "Bearer token is not valid.", http.StatusForbidden)
		return
	}

	result := token.Claims
	defer func() {
		out, err := json.Marshal(result)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	}()

	result["active"] = false
	claims := jwt.ClaimsCarrier(token.Claims)
	if claims.GetAudience() != h.Audience {
		log.WithFields(log.Fields{
			"introspect": "fail",
			"expted":     h.Audience,
			"actual":     claims.GetAudience(),
		}).Warn(`Token audience mismatch.`)
		return
	} else {
		result["active"] = token.Valid
		return
	}
}
コード例 #6
0
ファイル: guard.go プロジェクト: thanzen/hydra
func (g *Guard) PassesConditions(p policy.Policy, ctx *Context, permission, resource, subject string) (passes bool) {
	passes = len(p.GetConditions()) == 0
	for _, condition := range p.GetConditions() {
		op, ok := g.GetOperator(condition.GetOperator())
		if !ok {
			log.WithFields(log.Fields{
				"subjects": p.GetSubjects(),
				"subject":  subject,
			}).Warn("Could not check conditions.")
			return false
		}

		extra := condition.GetExtra()
		extra["permission"] = permission
		extra["resource"] = resource
		extra["subject"] = subject
		if !op(extra, ctx) {
			return false
		}

		passes = true
	}
	return passes
}