|
|
@@ -126,9 +126,11 @@ func hasGuestAccess(sec auth.Store, r *http.Request, key string) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-func writeNoAuth(w http.ResponseWriter) {
|
|
|
+func writeNoAuth(w http.ResponseWriter, r *http.Request) {
|
|
|
herr := httptypes.NewHTTPError(http.StatusUnauthorized, "Insufficient credentials")
|
|
|
- herr.WriteTo(w)
|
|
|
+ if err := herr.WriteTo(w); err != nil {
|
|
|
+ plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func handleAuth(mux *http.ServeMux, sh *authHandler) {
|
|
|
@@ -144,7 +146,7 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
if !hasRootAccess(sh.sec, r) {
|
|
|
- writeNoAuth(w)
|
|
|
+ writeNoAuth(w, r)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -153,7 +155,7 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
roles, err := sh.sec.AllRoles()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
if roles == nil {
|
|
|
@@ -162,7 +164,7 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
err = r.ParseForm()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -173,7 +175,7 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
var role auth.Role
|
|
|
role, err = sh.sec.GetRole(roleName)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
rolesCollections.Roles = append(rolesCollections.Roles, role)
|
|
|
@@ -182,7 +184,7 @@ func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
if err != nil {
|
|
|
plog.Warningf("baseRoles error encoding on %s", r.URL)
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -197,7 +199,7 @@ func (sh *authHandler) handleRoles(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
if len(pieces) != 3 {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
|
|
|
return
|
|
|
}
|
|
|
sh.forRole(w, r, pieces[2])
|
|
|
@@ -208,7 +210,7 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
|
|
return
|
|
|
}
|
|
|
if !hasRootAccess(sh.sec, r) {
|
|
|
- writeNoAuth(w)
|
|
|
+ writeNoAuth(w, r)
|
|
|
return
|
|
|
}
|
|
|
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
|
|
@@ -218,7 +220,7 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
|
|
case "GET":
|
|
|
data, err := sh.sec.GetRole(role)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
err = json.NewEncoder(w).Encode(data)
|
|
|
@@ -231,11 +233,11 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
|
|
var in auth.Role
|
|
|
err := json.NewDecoder(r.Body).Decode(&in)
|
|
|
if err != nil {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
|
|
|
return
|
|
|
}
|
|
|
if in.Role != role {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON name does not match the name in the URL"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON name does not match the name in the URL"))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -245,19 +247,19 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
|
|
if in.Grant.IsEmpty() && in.Revoke.IsEmpty() {
|
|
|
err = sh.sec.CreateRole(in)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
|
out = in
|
|
|
} else {
|
|
|
if !in.Permissions.IsEmpty() {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON contains both permissions and grant/revoke"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON contains both permissions and grant/revoke"))
|
|
|
return
|
|
|
}
|
|
|
out, err = sh.sec.UpdateRole(in)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
@@ -272,7 +274,7 @@ func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role stri
|
|
|
case "DELETE":
|
|
|
err := sh.sec.DeleteRole(role)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -288,7 +290,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
if !hasRootAccess(sh.sec, r) {
|
|
|
- writeNoAuth(w)
|
|
|
+ writeNoAuth(w, r)
|
|
|
return
|
|
|
}
|
|
|
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
|
|
@@ -296,7 +298,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
users, err := sh.sec.AllUsers()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
if users == nil {
|
|
|
@@ -305,7 +307,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
err = r.ParseForm()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -316,7 +318,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
var user auth.User
|
|
|
user, err = sh.sec.GetUser(userName)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -325,7 +327,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
var role auth.Role
|
|
|
role, err = sh.sec.GetRole(roleName)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
uwr.Roles = append(uwr.Roles, role)
|
|
|
@@ -337,7 +339,7 @@ func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
if err != nil {
|
|
|
plog.Warningf("baseUsers error encoding on %s", r.URL)
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -352,7 +354,7 @@ func (sh *authHandler) handleUsers(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
if len(pieces) != 3 {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path"))
|
|
|
return
|
|
|
}
|
|
|
sh.forUser(w, r, pieces[2])
|
|
|
@@ -363,7 +365,7 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
return
|
|
|
}
|
|
|
if !hasRootAccess(sh.sec, r) {
|
|
|
- writeNoAuth(w)
|
|
|
+ writeNoAuth(w, r)
|
|
|
return
|
|
|
}
|
|
|
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
|
|
@@ -373,13 +375,13 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
case "GET":
|
|
|
u, err := sh.sec.GetUser(user)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = r.ParseForm()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -388,7 +390,7 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
var role auth.Role
|
|
|
role, err = sh.sec.GetRole(roleName)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
uwr.Roles = append(uwr.Roles, role)
|
|
|
@@ -404,11 +406,11 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
var u auth.User
|
|
|
err := json.NewDecoder(r.Body).Decode(&u)
|
|
|
if err != nil {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body."))
|
|
|
return
|
|
|
}
|
|
|
if u.User != user {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON name does not match the name in the URL"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON name does not match the name in the URL"))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -428,18 +430,18 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
}
|
|
|
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
} else {
|
|
|
// update case
|
|
|
if len(u.Roles) != 0 {
|
|
|
- writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON contains both roles and grant/revoke"))
|
|
|
+ writeError(w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON contains both roles and grant/revoke"))
|
|
|
return
|
|
|
}
|
|
|
out, err = sh.sec.UpdateUser(u)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -461,7 +463,7 @@ func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user stri
|
|
|
case "DELETE":
|
|
|
err := sh.sec.DeleteUser(user)
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
@@ -476,7 +478,7 @@ func (sh *authHandler) enableDisable(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
if !hasWriteRootAccess(sh.sec, r) {
|
|
|
- writeNoAuth(w)
|
|
|
+ writeNoAuth(w, r)
|
|
|
return
|
|
|
}
|
|
|
w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String())
|
|
|
@@ -492,13 +494,13 @@ func (sh *authHandler) enableDisable(w http.ResponseWriter, r *http.Request) {
|
|
|
case "PUT":
|
|
|
err := sh.sec.EnableAuth()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
case "DELETE":
|
|
|
err := sh.sec.DisableAuth()
|
|
|
if err != nil {
|
|
|
- writeError(w, err)
|
|
|
+ writeError(w, r, err)
|
|
|
return
|
|
|
}
|
|
|
}
|