From 7cbb2225af72da6b53b31a64c7aeae74d176fa4a Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 5 Aug 2014 17:05:59 -0700 Subject: [PATCH] consul: Adding ACL endpoint --- consul/acl_endpoint.go | 91 ++++++++++++++++++++++++++++++++++++++++++ consul/server.go | 3 ++ 2 files changed, 94 insertions(+) create mode 100644 consul/acl_endpoint.go diff --git a/consul/acl_endpoint.go b/consul/acl_endpoint.go new file mode 100644 index 0000000000..ac9b0cdab1 --- /dev/null +++ b/consul/acl_endpoint.go @@ -0,0 +1,91 @@ +package consul + +import ( + "fmt" + "github.com/armon/go-metrics" + "github.com/hashicorp/consul/consul/structs" + "time" +) + +// ACL endpoint is used to manipulate ACLs +type ACL struct { + srv *Server +} + +// Apply is used to apply a modifying request to the data store. This should +// only be used for operations that modify the data +func (a *ACL) Apply(args *structs.ACLRequest, reply *string) error { + if done, err := a.srv.forward("ACL.Apply", args, args, reply); done { + return err + } + defer metrics.MeasureSince([]string{"consul", "acl", "apply"}, time.Now()) + + // Verify the args + switch args.ACL.Type { + case structs.ACLTypeClient: + case structs.ACLTypeManagement: + default: + return fmt.Errorf("Invalid ACL Type") + } + + // TODO: Verify ACL compiles... + if args.Op == structs.ACLSet { + } + + // Apply the update + resp, err := a.srv.raftApply(structs.ACLRequestType, args) + if err != nil { + a.srv.logger.Printf("[ERR] consul.acl: Apply failed: %v", err) + return err + } + if respErr, ok := resp.(error); ok { + return respErr + } + + // Check if the return type is a string + if respString, ok := resp.(string); ok { + *reply = respString + } + return nil +} + +// Get is used to retrieve a single ACL +func (a *ACL) Get(args *structs.ACLSpecificRequest, + reply *structs.IndexedACLs) error { + if done, err := a.srv.forward("ACL.Get", args, args, reply); done { + return err + } + + // Get the local state + state := a.srv.fsm.State() + return a.srv.blockingRPC(&args.QueryOptions, + &reply.QueryMeta, + state.QueryTables("ACLGet"), + func() error { + index, acl, err := state.ACLGet(args.ACL) + reply.Index = index + if acl != nil { + reply.ACLs = structs.ACLs{acl} + } + return err + }) +} + +// List is used to list all the ACLs +func (a *ACL) List(args *structs.DCSpecificRequest, + reply *structs.IndexedACLs) error { + if done, err := a.srv.forward("ACL.List", args, args, reply); done { + return err + } + + // Get the local state + state := a.srv.fsm.State() + return a.srv.blockingRPC(&args.QueryOptions, + &reply.QueryMeta, + state.QueryTables("ACLList"), + func() error { + var err error + reply.Index, reply.ACLs, err = state.ACLList() + return err + }) +} diff --git a/consul/server.go b/consul/server.go index 927b7a74d9..b07522e156 100644 --- a/consul/server.go +++ b/consul/server.go @@ -125,6 +125,7 @@ type endpoints struct { KVS *KVS Session *Session Internal *Internal + ACL *ACL } // NewServer is used to construct a new Consul server from the @@ -341,6 +342,7 @@ func (s *Server) setupRPC(tlsConfig *tls.Config) error { s.endpoints.KVS = &KVS{s} s.endpoints.Session = &Session{s} s.endpoints.Internal = &Internal{s} + s.endpoints.ACL = &ACL{s} // Register the handlers s.rpcServer.Register(s.endpoints.Status) @@ -349,6 +351,7 @@ func (s *Server) setupRPC(tlsConfig *tls.Config) error { s.rpcServer.Register(s.endpoints.KVS) s.rpcServer.Register(s.endpoints.Session) s.rpcServer.Register(s.endpoints.Internal) + s.rpcServer.Register(s.endpoints.ACL) list, err := net.ListenTCP("tcp", s.config.RPCAddr) if err != nil {