forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 0
/
acl.go
95 lines (84 loc) · 2.77 KB
/
acl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package acl contains functions to enforce access control lists.
// It allows you to register multiple security policies for enforcing
// ACLs for users or HTTP requests. The specific policy to use must be
// specified from a command line argument and cannot be changed on-the-fly.
package acl
import (
"flag"
"fmt"
"net/http"
"sync"
log "github.com/golang/glog"
)
// This is a list of predefined roles. Applications are free
// to invent more roles, as long as the acl policies they use can
// understand what they mean.
const (
ADMIN = "admin"
DEBUGGING = "debugging"
MONITORING = "monitoring"
)
var (
securityPolicy = flag.String("security_policy", "", "security policy to enforce for URLs")
policies = make(map[string]Policy)
once sync.Once
currentPolicy Policy
)
// Policy defines the interface that needs to be satisfied by
// ACL policy implementors.
type Policy interface {
// CheckAccessActor can be called to verify if an actor
// has access to the role.
CheckAccessActor(actor, role string) error
// CheckAccessHTTP can be called to verify if an actor in
// the http request has access to the role.
CheckAccessHTTP(req *http.Request, role string) error
}
// RegisterPolicy registers a security policy. This function must be called
// before the first call to CheckAccess happens, preferably through an init.
// This will ensure that the requested policy can be found by other acl
// functions when needed.
func RegisterPolicy(name string, policy Policy) {
if _, ok := policies[name]; ok {
log.Fatalf("policy %s is already registered", name)
}
policies[name] = policy
}
func savePolicy() {
if *securityPolicy == "" {
return
}
currentPolicy = policies[*securityPolicy]
if currentPolicy == nil {
log.Warningf("policy %s not found, using fallback policy", *securityPolicy)
currentPolicy = FallbackPolicy{}
}
}
// CheckAccessActor uses the current security policy to
// verify if an actor has access to the role.
func CheckAccessActor(actor, role string) error {
once.Do(savePolicy)
if currentPolicy != nil {
return currentPolicy.CheckAccessActor(actor, role)
}
return nil
}
// CheckAccessHTTP uses the current security policy to
// verify if an actor in an http request has access to
// the role.
func CheckAccessHTTP(req *http.Request, role string) error {
once.Do(savePolicy)
if currentPolicy != nil {
return currentPolicy.CheckAccessHTTP(req, role)
}
return nil
}
// SendError is a convenience function that sends an ACL
// error as an HTTP response.
func SendError(w http.ResponseWriter, err error) {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "Access denied: %v\n", err)
}