Example #1
0
File: app.go Project: Endika/tsuru
func getEnv(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	var variables []string
	if r.Body != nil {
		defer r.Body.Close()
		err := json.NewDecoder(r.Body).Decode(&variables)
		if err != nil && err != io.EOF {
			return err
		}
	}
	appName := r.URL.Query().Get(":app")
	var u *auth.User
	var err error
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	if !t.IsAppToken() {
		u, err = t.User()
		if err != nil {
			return err
		}
		rec.Log(u.Email, "get-env", "app="+appName, fmt.Sprintf("envs=%s", variables))
		allowed := permission.Check(t, permission.PermAppReadEnv,
			append(permission.Contexts(permission.CtxTeam, a.Teams),
				permission.Context(permission.CtxApp, a.Name),
				permission.Context(permission.CtxPool, a.Pool),
			)...,
		)
		if !allowed {
			return permission.ErrUnauthorized
		}
	}
	return writeEnvVars(w, &a, variables...)
}
Example #2
0
func listContainersHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	address := r.URL.Query().Get(":address")
	if address != "" {
		node, err := mainDockerProvisioner.Cluster().GetNode(address)
		if err != nil {
			return err
		}
		hasAccess := permission.Check(t, permission.PermNodeRead,
			permission.Context(permission.CtxPool, node.Metadata["pool"]))
		if !hasAccess {
			return permission.ErrUnauthorized
		}
		containerList, err := mainDockerProvisioner.listContainersByHost(address)
		if err != nil {
			return err
		}
		return json.NewEncoder(w).Encode(containerList)
	}
	appName := r.URL.Query().Get(":appname")
	a, err := app.GetByName(appName)
	if err != nil {
		return err
	}
	hasAccess := permission.Check(t, permission.PermNodeRead,
		permission.Context(permission.CtxPool, a.Pool))
	if !hasAccess {
		return permission.ErrUnauthorized
	}
	containerList, err := mainDockerProvisioner.listContainersByApp(appName)
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(containerList)
}
Example #3
0
File: app.go Project: Endika/tsuru
func appDelete(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	a, err := getAppFromContext(r.URL.Query().Get(":app"), r)
	if err != nil {
		return err
	}
	canDelete := permission.Check(t, permission.PermAppDelete,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !canDelete {
		return permission.ErrUnauthorized
	}
	rec.Log(u.Email, "app-delete", "app="+a.Name)
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	err = app.Delete(&a, writer)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
	}
	return nil
}
Example #4
0
func (s *S) TestNewWithPermission(c *check.C) {
	evt, err := New(&Opts{
		Target: Target{Type: "app", Value: "myapp"},
		Kind:   permission.PermAppUpdateEnvSet,
		Owner:  s.token,
		Allowed: Allowed(permission.PermAppReadEvents,
			permission.Context(permission.CtxApp, "myapp"), permission.Context(permission.CtxTeam, "myteam")),
	})
	c.Assert(err, check.IsNil)
	expected := &Event{eventData: eventData{
		ID:             eventID{Target: Target{Type: "app", Value: "myapp"}},
		UniqueID:       evt.UniqueID,
		Target:         Target{Type: "app", Value: "myapp"},
		Kind:           Kind{Type: KindTypePermission, Name: "app.update.env.set"},
		Owner:          Owner{Type: OwnerTypeUser, Name: s.token.GetUserName()},
		Running:        true,
		StartTime:      evt.StartTime,
		LockUpdateTime: evt.LockUpdateTime,
		Allowed: AllowedPermission{
			Scheme:   permission.PermAppReadEvents.FullName(),
			Contexts: []permission.PermissionContext{permission.Context(permission.CtxApp, "myapp"), permission.Context(permission.CtxTeam, "myteam")},
		},
	}}
	c.Assert(evt, check.DeepEquals, expected)
	evts, err := All()
	c.Assert(err, check.IsNil)
	c.Assert(evts, check.HasLen, 1)
	evts[0].StartTime = expected.StartTime
	evts[0].LockUpdateTime = expected.LockUpdateTime
	c.Assert(&evts[0], check.DeepEquals, expected)
}
Example #5
0
func (s *EventSuite) TestEventInfoPermission(c *check.C) {
	token := customUserWithPermission(c, "myuser", permission.Permission{
		Scheme:  permission.PermAppRead,
		Context: permission.Context(permission.CtxTeam, s.team.Name),
	})
	evt, err := event.New(&event.Opts{
		Target:  event.Target{Type: event.TargetTypeApp, Value: "aha"},
		Owner:   s.token,
		Kind:    permission.PermAppDeploy,
		Allowed: event.Allowed(permission.PermAppReadEvents, permission.Context(permission.CtxTeam, s.team.Name)),
	})
	c.Assert(err, check.IsNil)
	u := fmt.Sprintf("/events/%s", evt.UniqueID.Hex())
	request, err := http.NewRequest("GET", u, nil)
	c.Assert(err, check.IsNil)
	request.Header.Set("Authorization", "bearer "+token.GetValue())
	recorder := httptest.NewRecorder()
	server := RunServer(true)
	server.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	var result event.Event
	err = json.Unmarshal(recorder.Body.Bytes(), &result)
	c.Assert(err, check.IsNil)
	c.Assert(result.Kind, check.DeepEquals, evt.Kind)
	c.Assert(result.Target, check.DeepEquals, evt.Target)
}
Example #6
0
func BaseTokenPermission(t Token) ([]permission.Permission, error) {
	if t.IsAppToken() {
		// TODO(cezarsa): Improve handling of app tokens. These permissions
		// listed here are the ones required by deploy-agent and legacy tsuru-
		// unit-agent.
		return []permission.Permission{
			{
				Scheme:  permission.PermAppUpdateUnitRegister,
				Context: permission.Context(permission.CtxApp, t.GetAppName()),
			},
			{
				Scheme:  permission.PermAppUpdateLog,
				Context: permission.Context(permission.CtxApp, t.GetAppName()),
			},
			{
				Scheme:  permission.PermAppUpdateUnitStatus,
				Context: permission.Context(permission.CtxApp, t.GetAppName()),
			},
			{
				Scheme:  permission.PermAppReadDeploy,
				Context: permission.Context(permission.CtxApp, t.GetAppName()),
			},
		}, nil
	}
	user, err := t.User()
	if err != nil {
		return nil, err
	}
	return user.Permissions()
}
Example #7
0
func (s *S) TestListUsersWithPermissions(c *check.C) {
	u1 := User{Email: "*****@*****.**", Password: "******"}
	err := u1.Create()
	c.Assert(err, check.IsNil)
	u2 := User{Email: "*****@*****.**", Password: "******"}
	err = u2.Create()
	c.Assert(err, check.IsNil)
	r1, err := permission.NewRole("r1", "app", "")
	c.Assert(err, check.IsNil)
	err = r1.AddPermissions("app.update.env", "app.deploy")
	c.Assert(err, check.IsNil)
	err = u1.AddRole("r1", "myapp1")
	c.Assert(err, check.IsNil)
	err = u2.AddRole("r1", "myapp2")
	c.Assert(err, check.IsNil)
	users, err := ListUsersWithPermissions(permission.Permission{
		Scheme:  permission.PermAppDeploy,
		Context: permission.Context(permission.CtxApp, "myapp1"),
	})
	c.Assert(err, check.IsNil)
	c.Assert(users, check.HasLen, 1)
	c.Assert(users[0].Email, check.Equals, u1.Email)
	users, err = ListUsersWithPermissions(permission.Permission{
		Scheme:  permission.PermAppDeploy,
		Context: permission.Context(permission.CtxApp, "myapp2"),
	})
	c.Assert(err, check.IsNil)
	c.Assert(users, check.HasLen, 1)
	c.Assert(users[0].Email, check.Equals, u2.Email)
}
Example #8
0
func (s *S) TestDissociateRoleNotAuthorized(c *check.C) {
	role, err := permission.NewRole("test", "team")
	c.Assert(err, check.IsNil)
	err = role.AddPermissions("app.create")
	c.Assert(err, check.IsNil)
	otherToken := customUserWithPermission(c, "user2")
	otherUser, err := otherToken.User()
	c.Assert(err, check.IsNil)
	err = otherUser.AddRole(role.Name, "myteam")
	c.Assert(err, check.IsNil)
	url := fmt.Sprintf("/roles/test/user/%s?context=myteam", otherToken.GetUserName())
	req, err := http.NewRequest("DELETE", url, nil)
	c.Assert(err, check.IsNil)
	token := customUserWithPermission(c, "user1", permission.Permission{
		Scheme:  permission.PermRoleUpdateDissociate,
		Context: permission.Context(permission.CtxGlobal, ""),
	}, permission.Permission{
		Scheme:  permission.PermAppCreate,
		Context: permission.Context(permission.CtxTeam, "otherteam"),
	})
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "bearer "+token.GetValue())
	recorder := httptest.NewRecorder()
	server := RunServer(true)
	server.ServeHTTP(recorder, req)
	c.Assert(err, check.IsNil)
	c.Assert(recorder.Code, check.Equals, http.StatusForbidden)
	c.Assert(recorder.Body.String(), check.Equals, "User not authorized to use permission app.create(team myteam)\n")
	otherUser, err = otherToken.User()
	c.Assert(err, check.IsNil)
	c.Assert(otherUser.Roles, check.HasLen, 1)
}
Example #9
0
func unsetCName(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	cnames := r.URL.Query()["cname"]
	if len(cnames) == 0 {
		msg := "You must provide the cname."
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdateCnameRemove,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	rec.Log(u.Email, "remove-cname", "app="+appName, "cnames="+strings.Join(cnames, ", "))
	if err = a.RemoveCName(cnames...); err == nil {
		return nil
	}
	if err.Error() == "Invalid cname" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	return err
}
Example #10
0
File: plan.go Project: Endika/tsuru
func changePlan(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	var plan app.Plan
	err := json.NewDecoder(r.Body).Decode(&plan)
	if err != nil {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "unable to parse request body",
		}
	}
	a, err := getAppFromContext(r.URL.Query().Get(":app"), r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdatePlan,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	keepAliveWriter := io.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &io.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	err = a.ChangePlan(plan.Name, writer)
	if err == app.ErrPlanNotFound {
		writer.Encode(io.SimpleJsonMessage{Error: err.Error()})
		return err
	}
	return err
}
Example #11
0
func (s *S) TestPoolListHandlerWithPermissionToDefault(c *check.C) {
	team := auth.Team{Name: "angra"}
	err := s.conn.Teams().Insert(team)
	c.Assert(err, check.IsNil)
	perms := []permission.Permission{
		{
			Scheme:  permission.PermAppCreate,
			Context: permission.Context(permission.CtxGlobal, ""),
		},
		{
			Scheme:  permission.PermPoolUpdate,
			Context: permission.Context(permission.CtxGlobal, ""),
		},
	}
	token := userWithPermission(c, perms...)
	pool := provision.Pool{Name: "pool1", Teams: []string{team.Name}}
	opts := provision.AddPoolOptions{Name: pool.Name, Default: pool.Default}
	err = provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	err = provision.AddTeamsToPool(pool.Name, pool.Teams)
	c.Assert(err, check.IsNil)
	defer provision.RemovePool(pool.Name)
	req, err := http.NewRequest("GET", "/pools", nil)
	c.Assert(err, check.IsNil)
	rec := httptest.NewRecorder()
	err = poolList(rec, req, token)
	c.Assert(err, check.IsNil)
	var pools []provision.Pool
	err = json.NewDecoder(rec.Body).Decode(&pools)
	c.Assert(err, check.IsNil)
	c.Assert(pools, check.HasLen, 2)
	c.Assert(pools[0].Name, check.Equals, "test1")
	c.Assert(pools[1].Name, check.Equals, "pool1")
}
Example #12
0
File: app.go Project: Endika/tsuru
func restart(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	process := r.URL.Query().Get("process")
	w.Header().Set("Content-Type", "text")
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdateRestart,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	rec.Log(u.Email, "restart", "app="+appName)
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	err = a.Restart(process, writer)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
		return err
	}
	return nil
}
Example #13
0
File: app.go Project: Endika/tsuru
func appChangePool(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	a, err := getAppFromContext(r.URL.Query().Get(":app"), r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdatePool,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	defer r.Body.Close()
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: fmt.Sprintf("Unable to decode body: %s", err.Error()),
		}
	}
	pool := string(data)
	rec.Log(u.Email, "app-change-pool", "app="+r.URL.Query().Get(":app"), "pool="+pool)
	return a.ChangePool(pool)
}
Example #14
0
func deployDataToEvent(data *DeployData) error {
	var evt event.Event
	evt.UniqueID = data.ID
	evt.Target = event.Target{Type: event.TargetTypeApp, Value: data.App}
	evt.Owner = event.Owner{Type: event.OwnerTypeUser, Name: data.User}
	evt.Kind = event.Kind{Type: event.KindTypePermission, Name: permission.PermAppDeploy.FullName()}
	evt.StartTime = data.Timestamp
	evt.EndTime = data.Timestamp.Add(data.Duration)
	evt.Error = data.Error
	evt.Log = data.Log
	evt.RemoveDate = data.RemoveDate
	a, err := GetByName(data.App)
	if err == nil {
		evt.Allowed = event.Allowed(permission.PermAppReadEvents, append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...)
	} else {
		evt.Allowed = event.Allowed(permission.PermAppReadEvents)
	}
	startOpts := DeployOptions{
		Commit: data.Commit,
		Origin: data.Origin,
	}
	var otherData map[string]string
	if data.Diff != "" {
		otherData = map[string]string{"diff": data.Diff}
	}
	endData := map[string]string{"image": data.Image}
	err = evt.RawInsert(startOpts, otherData, endData)
	if mgo.IsDup(err) {
		return nil
	}
	return err
}
Example #15
0
// addNodeHandler can provide an machine and/or register a node address.
// If register flag is true, it will just register a node.
// It checks if node address is valid and accessible.
func addNodeHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	params, err := unmarshal(r.Body)
	if err != nil {
		return err
	}
	if templateName, ok := params["template"]; ok {
		params, err = iaas.ExpandTemplate(templateName)
		if err != nil {
			w.WriteHeader(http.StatusBadRequest)
			return json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
		}
	}
	pool := params["pool"]
	if pool == "" {
		w.WriteHeader(http.StatusBadRequest)
		return json.NewEncoder(w).Encode(map[string]string{"error": "pool is required"})
	}
	if !permission.Check(t, permission.PermNodeCreate, permission.Context(permission.CtxPool, pool)) {
		return permission.ErrUnauthorized
	}
	isRegister, _ := strconv.ParseBool(r.URL.Query().Get("register"))
	if !isRegister {
		canCreateMachine := permission.Check(t, permission.PermMachineCreate,
			permission.Context(permission.CtxIaaS, params["iaas"]))
		if !canCreateMachine {
			return permission.ErrUnauthorized
		}
	}
	response, err := mainDockerProvisioner.addNodeForParams(params, isRegister)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		response["error"] = err.Error()
	}
	return json.NewEncoder(w).Encode(response)
}
Example #16
0
func (s *S) TestAssignRoleCheckGandalf(c *check.C) {
	role, err := permission.NewRole("test", "app", "")
	c.Assert(err, check.IsNil)
	err = role.AddPermissions("app.deploy")
	c.Assert(err, check.IsNil)
	emptyToken := customUserWithPermission(c, "user2")
	a := app.App{Name: "myapp", TeamOwner: s.team.Name}
	err = app.CreateApp(&a, s.user)
	c.Assert(err, check.IsNil)
	roleBody := bytes.NewBufferString(fmt.Sprintf("email=%s&context=myapp", emptyToken.GetUserName()))
	req, err := http.NewRequest("POST", "/roles/test/user", roleBody)
	c.Assert(err, check.IsNil)
	token := customUserWithPermission(c, "user1", permission.Permission{
		Scheme:  permission.PermRoleUpdateAssign,
		Context: permission.Context(permission.CtxGlobal, ""),
	}, permission.Permission{
		Scheme:  permission.PermAppDeploy,
		Context: permission.Context(permission.CtxApp, "myapp"),
	})
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "bearer "+token.GetValue())
	recorder := httptest.NewRecorder()
	server := RunServer(true)
	server.ServeHTTP(recorder, req)
	c.Assert(err, check.IsNil)
	c.Assert(recorder.Code, check.Equals, http.StatusOK)
	emptyUser, err := emptyToken.User()
	c.Assert(err, check.IsNil)
	users, err := repositorytest.Granted("myapp")
	c.Assert(err, check.IsNil)
	c.Assert(users, check.DeepEquals, []string{s.user.Email, emptyToken.GetUserName()})
	c.Assert(emptyUser.Roles, check.HasLen, 1)
}
Example #17
0
File: auth.go Project: tsuru/tsuru
// title: regenerate token
// path: /users/api-key
// method: POST
// produce: application/json
// responses:
//   200: OK
//   401: Unauthorized
//   404: User not found
func regenerateAPIToken(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	r.ParseForm()
	email := r.URL.Query().Get("user")
	if email == "" {
		email = t.GetUserName()
	}
	allowed := permission.Check(t, permission.PermUserUpdateToken,
		permission.Context(permission.CtxUser, email),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	evt, err := event.New(&event.Opts{
		Target:     userTarget(email),
		Kind:       permission.PermUserUpdateToken,
		Owner:      t,
		CustomData: event.FormToCustomData(r.Form),
		Allowed:    event.Allowed(permission.PermUserReadEvents, permission.Context(permission.CtxUser, email)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u, err := auth.GetUserByEmail(email)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	apiKey, err := u.RegenerateAPIKey()
	if err != nil {
		return err
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(apiKey)
}
Example #18
0
File: auth.go Project: tsuru/tsuru
// title: remove team
// path: /teams/{name}
// method: DELETE
// responses:
//   200: Team removed
//   401: Unauthorized
//   403: Forbidden
//   404: Not found
func removeTeam(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	r.ParseForm()
	name := r.URL.Query().Get(":name")
	allowed := permission.Check(t, permission.PermTeamDelete,
		permission.Context(permission.CtxTeam, name),
	)
	if !allowed {
		return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf(`Team "%s" not found.`, name)}
	}
	evt, err := event.New(&event.Opts{
		Target:     teamTarget(name),
		Kind:       permission.PermTeamDelete,
		Owner:      t,
		CustomData: event.FormToCustomData(r.Form),
		Allowed:    event.Allowed(permission.PermTeamReadEvents, permission.Context(permission.CtxTeam, name)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	err = auth.RemoveTeam(name)
	if err != nil {
		if _, ok := err.(*auth.ErrTeamStillUsed); ok {
			msg := fmt.Sprintf("This team cannot be removed because there are still references to it:\n%s", err)
			return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
		}
		if err == auth.ErrTeamNotFound {
			return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf(`Team "%s" not found.`, name)}
		}
		return err
	}
	return nil
}
Example #19
0
func (s *EventSuite) TestEventCancelWithoutPermission(c *check.C) {
	token := customUserWithPermission(c, "myuser", permission.Permission{
		Scheme:  permission.PermAppRead,
		Context: permission.Context(permission.CtxTeam, s.team.Name),
	})
	evt, err := event.New(&event.Opts{
		Target:        event.Target{Type: event.TargetTypeApp, Value: "anything"},
		Owner:         s.token,
		Kind:          permission.PermAppDeploy,
		Cancelable:    true,
		Allowed:       event.Allowed(permission.PermAppReadEvents, permission.Context(permission.CtxTeam, s.team.Name)),
		AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, permission.Context(permission.CtxTeam, "other-team")),
	})
	c.Assert(err, check.IsNil)
	body := strings.NewReader("reason=we ain't gonna take it")
	u := fmt.Sprintf("/events/%s/cancel", evt.UniqueID.Hex())
	request, err := http.NewRequest("POST", u, body)
	c.Assert(err, check.IsNil)
	request.Header.Set("Authorization", "bearer "+token.GetValue())
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	recorder := httptest.NewRecorder()
	server := RunServer(true)
	server.ServeHTTP(recorder, request)
	c.Assert(recorder.Code, check.Equals, http.StatusForbidden)
}
Example #20
0
File: app.go Project: Endika/tsuru
func appRebuildRoutes(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	a, err := getAppFromContext(r.URL.Query().Get(":app"), r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppAdminRoutes,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	rec.Log(u.Email, "app-rebuild-routes", "app="+r.URL.Query().Get(":app"))
	w.Header().Set("Content-Type", "application/json")
	result, err := a.RebuildRoutes()
	if err != nil {
		return err
	}
	return json.NewEncoder(w).Encode(&result)
}
Example #21
0
func (s *EventSuite) insertEvents(target string, c *check.C) ([]*event.Event, error) {
	t, err := event.GetTargetType(target)
	if err != nil {
		return nil, err
	}
	evts := make([]*event.Event, 10)
	for i := 0; i < 10; i++ {
		name := fmt.Sprintf("app-%d", i)
		opts := &event.Opts{
			Target:     event.Target{Type: t, Value: name},
			Owner:      s.token,
			Kind:       permission.PermAppDeploy,
			Cancelable: i == 0,
		}
		if t == event.TargetTypeApp {
			opts.Allowed = event.Allowed(permission.PermAppReadEvents, permission.Context(permission.CtxTeam, s.team.Name))
			opts.AllowedCancel = event.Allowed(permission.PermAppUpdateEvents, permission.Context(permission.CtxTeam, s.team.Name))
		} else {
			opts.Allowed = event.Allowed(permission.PermApp)
			opts.AllowedCancel = event.Allowed(permission.PermApp)
		}
		evt, err := event.New(opts)
		c.Assert(err, check.IsNil)
		if i == 1 {
			err = evt.Done(nil)
			c.Assert(err, check.IsNil)
		}
		evts[i] = evt
	}
	return evts, nil
}
Example #22
0
File: app.go Project: Endika/tsuru
func updateApp(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	var updateData app.App
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &updateData); err != nil {
		return err
	}
	appName := r.URL.Query().Get(":appname")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	if updateData.Description != "" {
		allowed := permission.Check(t, permission.PermAppUpdate,
			append(permission.Contexts(permission.CtxTeam, a.Teams),
				permission.Context(permission.CtxApp, a.Name),
				permission.Context(permission.CtxPool, a.Pool),
			)...,
		)
		if !allowed {
			return permission.ErrUnauthorized
		}
		a.Description = updateData.Description
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	rec.Log(u.Email, "update-app", "app="+a.Name, "description="+a.Description)
	return a.Update()
}
Example #23
0
func (s *ConsumptionSuite) SetUpTest(c *check.C) {
	repositorytest.Reset()
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "tsuru_api_consumption_test")
	config.Set("auth:hash-cost", 4)
	config.Set("repo-manager", "fake")
	var err error
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	dbtest.ClearAllCollections(s.conn.Apps().Database)
	s.team = &auth.Team{Name: "tsuruteam"}
	err = s.conn.Teams().Insert(s.team)
	c.Assert(err, check.IsNil)
	s.token = customUserWithPermission(c, "consumption-master-user", permission.Permission{
		Scheme:  permission.PermServiceInstance,
		Context: permission.Context(permission.CtxTeam, s.team.Name),
	}, permission.Permission{
		Scheme:  permission.PermServiceRead,
		Context: permission.Context(permission.CtxTeam, s.team.Name),
	})
	s.user, err = s.token.User()
	c.Assert(err, check.IsNil)
	app.AuthScheme = nativeScheme
	s.provisioner = provisiontest.NewFakeProvisioner()
	app.Provisioner = s.provisioner
}
Example #24
0
func sleep(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	process := r.URL.Query().Get("process")
	w.Header().Set("Content-Type", "text")
	u, err := t.User()
	if err != nil {
		return err
	}
	appName := r.URL.Query().Get(":app")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	proxy := r.URL.Query().Get("proxy")
	if proxy == "" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "Empty proxy URL"}
	}
	proxyURL, err := url.Parse(proxy)
	if err != nil {
		log.Errorf("Invalid url for proxy param: %v", proxy)
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdateSleep,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	rec.Log(u.Email, "sleep", "app="+appName)
	return a.Sleep(w, process, proxyURL)
}
Example #25
0
func (s *S) TestAssignRoleNotAuthorized(c *check.C) {
	role, err := permission.NewRole("test", "team")
	c.Assert(err, check.IsNil)
	err = role.AddPermissions("app.create")
	c.Assert(err, check.IsNil)
	emptyToken := customUserWithPermission(c, "user2")
	roleBody := bytes.NewBufferString(fmt.Sprintf("email=%s&context=myteam", emptyToken.GetUserName()))
	req, err := http.NewRequest("POST", "/roles/test/user", roleBody)
	c.Assert(err, check.IsNil)
	token := userWithPermission(c, permission.Permission{
		Scheme:  permission.PermRoleUpdateAssign,
		Context: permission.Context(permission.CtxGlobal, ""),
	}, permission.Permission{
		Scheme:  permission.PermAppCreate,
		Context: permission.Context(permission.CtxTeam, "otherteam"),
	})
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", "bearer "+token.GetValue())
	recorder := httptest.NewRecorder()
	server := RunServer(true)
	server.ServeHTTP(recorder, req)
	c.Assert(err, check.IsNil)
	c.Assert(recorder.Code, check.Equals, http.StatusForbidden)
	c.Assert(recorder.Body.String(), check.Equals, "User not authorized to use permission app.create(team myteam)\n")
	emptyUser, err := emptyToken.User()
	c.Assert(err, check.IsNil)
	c.Assert(emptyUser.Roles, check.HasLen, 0)
}
Example #26
0
func (s *S) TestUserPermissionsWithRemovedRole(c *check.C) {
	role, err := permission.NewRole("test", "team")
	c.Assert(err, check.IsNil)
	u := User{Email: "*****@*****.**", Password: "******"}
	err = u.Create()
	c.Assert(err, check.IsNil)
	err = u.AddRole(role.Name, "team")
	c.Assert(err, check.IsNil)
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	err = conn.Roles().RemoveId(role.Name)
	c.Assert(err, check.IsNil)
	perms, err := u.Permissions()
	c.Assert(err, check.IsNil)
	c.Assert(perms, check.IsNil)
	r1, err := permission.NewRole("r1", "app")
	c.Assert(err, check.IsNil)
	err = r1.AddPermissions("app.update.env", "app.deploy")
	c.Assert(err, check.IsNil)
	err = u.AddRole("r1", "myapp")
	c.Assert(err, check.IsNil)
	err = u.AddRole("r1", "myapp2")
	c.Assert(err, check.IsNil)
	perms, err = u.Permissions()
	c.Assert(err, check.IsNil)
	c.Assert(perms, check.DeepEquals, []permission.Permission{
		{Scheme: permission.PermAppDeploy, Context: permission.Context(permission.CtxApp, "myapp")},
		{Scheme: permission.PermAppUpdateEnv, Context: permission.Context(permission.CtxApp, "myapp")},
		{Scheme: permission.PermAppDeploy, Context: permission.Context(permission.CtxApp, "myapp2")},
		{Scheme: permission.PermAppUpdateEnv, Context: permission.Context(permission.CtxApp, "myapp2")},
	})
}
Example #27
0
// title: set envs
// path: /apps/{app}/env
// method: POST
// consume: application/x-www-form-urlencoded
// produce: application/x-json-stream
// responses:
//   200: Envs updated
//   400: Invalid data
//   401: Unauthorized
//   404: App not found
func setEnv(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	err := r.ParseForm()
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	var e Envs
	dec := form.NewDecoder(nil)
	dec.IgnoreUnknownKeys(true)
	err = dec.DecodeValues(&e, r.Form)
	if err != nil {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	}
	if len(e.Envs) == 0 {
		msg := "You must provide the list of environment variables"
		return &errors.HTTP{Code: http.StatusBadRequest, Message: msg}
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	extra := fmt.Sprintf("private=%t", e.Private)
	appName := r.URL.Query().Get(":app")
	a, err := getAppFromContext(appName, r)
	if err != nil {
		return err
	}
	allowed := permission.Check(t, permission.PermAppUpdateEnvSet,
		append(permission.Contexts(permission.CtxTeam, a.Teams),
			permission.Context(permission.CtxApp, a.Name),
			permission.Context(permission.CtxPool, a.Pool),
		)...,
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	envs := map[string]string{}
	variables := []bind.EnvVar{}
	for _, v := range e.Envs {
		envs[v.Name] = v.Value
		variables = append(variables, bind.EnvVar{Name: v.Name, Value: v.Value, Public: !e.Private})
	}
	rec.Log(u.Email, "set-env", "app="+appName, envs, extra)
	w.Header().Set("Content-Type", "application/x-json-stream")
	keepAliveWriter := tsuruIo.NewKeepAliveWriter(w, 30*time.Second, "")
	defer keepAliveWriter.Stop()
	writer := &tsuruIo.SimpleJsonMessageEncoderWriter{Encoder: json.NewEncoder(keepAliveWriter)}
	err = a.SetEnvs(
		bind.SetEnvApp{
			Envs:          variables,
			PublicOnly:    true,
			ShouldRestart: !e.NoRestart,
		}, writer)
	if err != nil {
		writer.Encode(tsuruIo.SimpleJsonMessage{Error: err.Error()})
		return nil
	}
	return nil
}
Example #28
0
// title: service instance create
// path: /services/{service}/instances
// method: POST
// consume: application/x-www-form-urlencoded
// responses:
//   201: Service created
//   400: Invalid data
//   401: Unauthorized
//   409: Service already exists
func createServiceInstance(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	serviceName := r.URL.Query().Get(":service")
	user, err := t.User()
	if err != nil {
		return err
	}
	srv, err := getService(serviceName)
	if err != nil {
		return err
	}
	instance := service.ServiceInstance{
		Name:        r.FormValue("name"),
		PlanName:    r.FormValue("plan"),
		TeamOwner:   r.FormValue("owner"),
		Description: r.FormValue("description"),
	}
	var teamOwner string
	if instance.TeamOwner == "" {
		teamOwner, err = permission.TeamForPermission(t, permission.PermServiceInstanceCreate)
		if err != nil {
			return err
		}
		instance.TeamOwner = teamOwner
	}
	allowed := permission.Check(t, permission.PermServiceInstanceCreate,
		permission.Context(permission.CtxTeam, instance.TeamOwner),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	if srv.IsRestricted {
		allowed := permission.Check(t, permission.PermServiceRead,
			append(permission.Contexts(permission.CtxTeam, srv.Teams),
				permission.Context(permission.CtxService, srv.Name))...,
		)
		if !allowed {
			return permission.ErrUnauthorized
		}
	}
	rec.Log(user.Email, "create-service-instance", fmt.Sprintf("%#v", instance))
	err = service.CreateServiceInstance(instance, &srv, user)
	if err == service.ErrInstanceNameAlreadyExists {
		return &errors.HTTP{
			Code:    http.StatusConflict,
			Message: err.Error(),
		}
	}
	if err == service.ErrInvalidInstanceName {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: err.Error(),
		}
	}
	if err == nil {
		w.WriteHeader(http.StatusCreated)
	}
	return err
}
Example #29
0
func updateNodeHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	params, err := unmarshal(r.Body)
	if err != nil {
		return err
	}
	address, _ := params["address"]
	if address == "" {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: "address is required"}
	}
	nodes, err := mainDockerProvisioner.Cluster().UnfilteredNodes()
	if err != nil {
		return err
	}
	var oldNode *cluster.Node
	for i := range nodes {
		if nodes[i].Address == address {
			oldNode = &nodes[i]
			break
		}
	}
	oldPool, _ := oldNode.Metadata["pool"]
	allowedOldPool := permission.Check(t, permission.PermNodeUpdate,
		permission.Context(permission.CtxPool, oldPool),
	)
	if !allowedOldPool {
		return permission.ErrUnauthorized
	}
	newPool, ok := params["pool"]
	if ok {
		allowedNewPool := permission.Check(t, permission.PermNodeUpdate,
			permission.Context(permission.CtxPool, newPool),
		)
		if !allowedNewPool {
			return permission.ErrUnauthorized
		}
	}
	delete(params, "address")
	node := cluster.Node{Address: address, Metadata: params}
	disabled, _ := strconv.ParseBool(r.URL.Query().Get("disabled"))
	enabled, _ := strconv.ParseBool(r.URL.Query().Get("enabled"))
	if disabled && enabled {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "You can't make a node enable and disable at the same time.",
		}
	}
	if disabled {
		node.CreationStatus = cluster.NodeCreationStatusDisabled
	}
	if enabled {
		node.CreationStatus = cluster.NodeStatusReady
	}
	_, err = mainDockerProvisioner.Cluster().UpdateNode(node)
	return err
}
Example #30
0
// removeNodeHandler calls scheduler.Unregister to unregistering a node into it.
func removeNodeHandler(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	params, err := unmarshal(r.Body)
	if err != nil {
		return err
	}
	address, _ := params["address"]
	if address == "" {
		return fmt.Errorf("Node address is required.")
	}
	node, err := mainDockerProvisioner.Cluster().GetNode(address)
	if err != nil {
		return err
	}
	allowedNodeRemove := permission.Check(t, permission.PermNodeDelete,
		permission.Context(permission.CtxPool, node.Metadata["pool"]),
	)
	if !allowedNodeRemove {
		return permission.ErrUnauthorized
	}
	removeIaaS, _ := strconv.ParseBool(params["remove_iaas"])
	if removeIaaS {
		allowedIaasRemove := permission.Check(t, permission.PermMachineDelete,
			permission.Context(permission.CtxIaaS, node.Metadata["iaas"]),
		)
		if !allowedIaasRemove {
			return permission.ErrUnauthorized
		}
	}
	node.CreationStatus = cluster.NodeCreationStatusDisabled
	_, err = mainDockerProvisioner.Cluster().UpdateNode(node)
	if err != nil {
		return err
	}
	noRebalance, err := strconv.ParseBool(r.URL.Query().Get("no-rebalance"))
	if !noRebalance {
		err = mainDockerProvisioner.rebalanceContainersByHost(urlToHost(address), w)
		if err != nil {
			return err
		}
	}
	err = mainDockerProvisioner.Cluster().Unregister(address)
	if err != nil {
		return err
	}
	if removeIaaS {
		var m iaas.Machine
		m, err = iaas.FindMachineByIdOrAddress(node.Metadata["iaas-id"], urlToHost(address))
		if err != nil && err != mgo.ErrNotFound {
			return err
		}
		return m.Destroy()
	}
	return nil
}