mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
commit
2690535f8a
82
etcdserver/etcdhttp/capability.go
Normal file
82
etcdserver/etcdhttp/capability.go
Normal file
@ -0,0 +1,82 @@
|
||||
package etcdhttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/go-semver/semver"
|
||||
"github.com/coreos/etcd/etcdserver"
|
||||
"github.com/coreos/etcd/etcdserver/etcdhttp/httptypes"
|
||||
)
|
||||
|
||||
type capability string
|
||||
|
||||
const (
|
||||
securityCapability capability = "security"
|
||||
)
|
||||
|
||||
var (
|
||||
// capabilityMap is a static map of version to capability map.
|
||||
// the base capabilities is the set of capability 2.0 supports.
|
||||
capabilityMaps = map[string]map[capability]bool{
|
||||
"2.1.0": {securityCapability: true},
|
||||
}
|
||||
|
||||
enableMapMu sync.Mutex
|
||||
// enabled points to a map in cpapbilityMaps
|
||||
enabledMap map[capability]bool
|
||||
)
|
||||
|
||||
// capabilityLoop checks the cluster version every 500ms and updates
|
||||
// the enabledCapability when the cluster version increased.
|
||||
// capabilityLoop MUST be ran in a goroutine before checking capability
|
||||
// or using capabilityHandler.
|
||||
func capabilityLoop(s *etcdserver.EtcdServer) {
|
||||
stopped := s.StopNotify()
|
||||
|
||||
var pv *semver.Version
|
||||
for {
|
||||
if v := s.ClusterVersion(); v != pv {
|
||||
if pv == nil {
|
||||
pv = v
|
||||
} else if v != nil && pv.LessThan(*v) {
|
||||
pv = v
|
||||
}
|
||||
enableMapMu.Lock()
|
||||
enabledMap = capabilityMaps[pv.String()]
|
||||
enableMapMu.Unlock()
|
||||
}
|
||||
|
||||
select {
|
||||
case <-stopped:
|
||||
return
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isCapabilityEnabled(c capability) bool {
|
||||
enableMapMu.Lock()
|
||||
defer enableMapMu.Unlock()
|
||||
if enabledMap == nil {
|
||||
return false
|
||||
}
|
||||
return enabledMap[c]
|
||||
}
|
||||
|
||||
func capabilityHandler(c capability, fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if !isCapabilityEnabled(c) {
|
||||
notCapable(w, c)
|
||||
return
|
||||
}
|
||||
fn(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func notCapable(w http.ResponseWriter, c capability) {
|
||||
herr := httptypes.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Not capable of accessing %s feature during rolling upgrades.", c))
|
||||
herr.WriteTo(w)
|
||||
}
|
@ -57,6 +57,8 @@ const (
|
||||
|
||||
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
|
||||
func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
|
||||
go capabilityLoop(server)
|
||||
|
||||
sec := security.NewStore(server, defaultServerTimeout)
|
||||
|
||||
kh := &keysHandler{
|
||||
@ -102,6 +104,7 @@ func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
|
||||
mux.Handle(membersPrefix+"/", mh)
|
||||
mux.Handle(deprecatedMachinesPrefix, dmh)
|
||||
handleSecurity(mux, sech)
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
|
@ -125,11 +125,11 @@ func writeNoAuth(w http.ResponseWriter) {
|
||||
}
|
||||
|
||||
func handleSecurity(mux *http.ServeMux, sh *securityHandler) {
|
||||
mux.HandleFunc(securityPrefix+"/roles", sh.baseRoles)
|
||||
mux.HandleFunc(securityPrefix+"/roles/", sh.handleRoles)
|
||||
mux.HandleFunc(securityPrefix+"/users", sh.baseUsers)
|
||||
mux.HandleFunc(securityPrefix+"/users/", sh.handleUsers)
|
||||
mux.HandleFunc(securityPrefix+"/enable", sh.enableDisable)
|
||||
mux.HandleFunc(securityPrefix+"/roles", capabilityHandler(securityCapability, sh.baseRoles))
|
||||
mux.HandleFunc(securityPrefix+"/roles/", capabilityHandler(securityCapability, sh.handleRoles))
|
||||
mux.HandleFunc(securityPrefix+"/users", capabilityHandler(securityCapability, sh.baseUsers))
|
||||
mux.HandleFunc(securityPrefix+"/users/", capabilityHandler(securityCapability, sh.handleUsers))
|
||||
mux.HandleFunc(securityPrefix+"/enable", capabilityHandler(securityCapability, sh.enableDisable))
|
||||
}
|
||||
|
||||
func (sh *securityHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user