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) }) } }
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 }
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}) }
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) }) }
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 } }
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 }