예제 #1
0
func NewUserManagerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*UserManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	resource, ok := resources.Get("createLocalLoginMacaroon").(common.ValueResource)
	if !ok {
		return nil, errors.NotFoundf("userAuth resource")
	}
	createLocalLoginMacaroon, ok := resource.Value.(func(names.UserTag) (*macaroon.Macaroon, error))
	if !ok {
		return nil, errors.NotValidf("userAuth resource")
	}

	return &UserManagerAPI{
		state:                    st,
		authorizer:               authorizer,
		createLocalLoginMacaroon: createLocalLoginMacaroon,
		check: common.NewBlockChecker(st),
	}, nil
}
예제 #2
0
파일: modelmanager.go 프로젝트: bac/juju
// NewModelManagerAPI creates a new api server endpoint for managing
// models.
func NewModelManagerAPI(
	st common.ModelManagerBackend,
	configGetter environs.EnvironConfigGetter,
	authorizer facade.Authorizer,
) (*ModelManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}
	// Since we know this is a user tag (because AuthClient is true),
	// we just do the type assertion to the UserTag.
	apiUser, _ := authorizer.GetAuthTag().(names.UserTag)
	// Pretty much all of the user manager methods have special casing for admin
	// users, so look once when we start and remember if the user is an admin.
	isAdmin, err := authorizer.HasPermission(permission.SuperuserAccess, st.ControllerTag())
	if err != nil {
		return nil, errors.Trace(err)
	}
	urlGetter := common.NewToolsURLGetter(st.ModelUUID(), st)
	return &ModelManagerAPI{
		ModelStatusAPI: common.NewModelStatusAPI(st, authorizer, apiUser),
		state:          st,
		check:          common.NewBlockChecker(st),
		authorizer:     authorizer,
		toolsFinder:    common.NewToolsFinder(configGetter, st, urlGetter),
		apiUser:        apiUser,
		isAdmin:        isAdmin,
	}, nil
}
예제 #3
0
파일: usermanager.go 프로젝트: bac/juju
func NewUserManagerAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*UserManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	// Since we know this is a user tag (because AuthClient is true),
	// we just do the type assertion to the UserTag.
	apiUser, _ := authorizer.GetAuthTag().(names.UserTag)
	// Pretty much all of the user manager methods have special casing for admin
	// users, so look once when we start and remember if the user is an admin.
	isAdmin, err := authorizer.HasPermission(permission.SuperuserAccess, st.ControllerTag())
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &UserManagerAPI{
		state:      st,
		authorizer: authorizer,
		check:      common.NewBlockChecker(st),
		apiUser:    apiUser,
		isAdmin:    isAdmin,
	}, nil
}
예제 #4
0
파일: block_test.go 프로젝트: imoapps/juju
func (s *blockCheckerSuite) SetUpTest(c *gc.C) {
	s.FakeJujuHomeSuite.SetUpTest(c)
	s.destroy = mockBlock{t: state.DestroyBlock, m: "Mock BLOCK testing: DESTROY"}
	s.remove = mockBlock{t: state.RemoveBlock, m: "Mock BLOCK testing: REMOVE"}
	s.change = mockBlock{t: state.ChangeBlock, m: "Mock BLOCK testing: CHANGE"}
	s.blockchecker = common.NewBlockChecker(s)
}
예제 #5
0
파일: modelconfig.go 프로젝트: bac/juju
// NewModelConfigAPI creates a new instance of the ModelConfig Facade.
func NewModelConfigAPI(backend Backend, authorizer facade.Authorizer) (*ModelConfigAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}
	client := &ModelConfigAPI{
		backend: backend,
		auth:    authorizer,
		check:   common.NewBlockChecker(backend),
	}
	return client, nil
}
예제 #6
0
// NewActionAPI returns an initialized ActionAPI
func NewActionAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*ActionAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	return &ActionAPI{
		state:      st,
		resources:  resources,
		authorizer: authorizer,
		check:      common.NewBlockChecker(st),
	}, nil
}
예제 #7
0
// NewImageManagerAPI creates a new server-side imagemanager API end point.
func NewImageManagerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*ImageManagerAPI, error) {
	// Only clients can access the image manager service.
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}
	return &ImageManagerAPI{
		state:      getState(st),
		resources:  resources,
		authorizer: authorizer,
		check:      common.NewBlockChecker(st),
	}, nil
}
예제 #8
0
func NewUserManagerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*UserManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	return &UserManagerAPI{
		state:      st,
		authorizer: authorizer,
		check:      common.NewBlockChecker(st),
	}, nil
}
예제 #9
0
파일: application.go 프로젝트: bac/juju
func newAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*API, error) {
	backend := NewStateBackend(st)
	blockChecker := common.NewBlockChecker(st)
	stateCharm := CharmToStateCharm
	return NewAPI(
		backend,
		authorizer,
		blockChecker,
		stateCharm,
	)
}
예제 #10
0
파일: get_test.go 프로젝트: bac/juju
func (s *getSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)

	s.authorizer = apiservertesting.FakeAuthorizer{
		Tag: s.AdminUserTag(c),
	}
	var err error
	backend := application.NewStateBackend(s.State)
	blockChecker := common.NewBlockChecker(s.State)
	s.serviceAPI, err = application.NewAPI(
		backend, s.authorizer, blockChecker,
		application.CharmToStateCharm,
	)
	c.Assert(err, jc.ErrorIsNil)
}
예제 #11
0
파일: client.go 프로젝트: mhilton/juju
// NewClient creates a new instance of the Client Facade.
func NewClient(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*Client, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}
	urlGetter := common.NewToolsURLGetter(st.EnvironUUID(), st)
	return &Client{
		api: &API{
			state:        st,
			auth:         authorizer,
			resources:    resources,
			statusSetter: common.NewStatusSetter(st, common.AuthAlways()),
			toolsFinder:  common.NewToolsFinder(st, st, urlGetter),
		},
		check: common.NewBlockChecker(st)}, nil
}
예제 #12
0
파일: storage.go 프로젝트: mhilton/juju
// AddToUnit validates and creates additional storage instances for units.
// This method handles bulk add operations and
// a failure on one individual storage instance does not block remaining
// instances from being processed.
// A "CHANGE" block can block this operation.
func (a *API) AddToUnit(args params.StoragesAddParams) (params.ErrorResults, error) {
	// Check if changes are allowed and the operation may proceed.
	blockChecker := common.NewBlockChecker(a.storage)
	if err := blockChecker.ChangeAllowed(); err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}

	if len(args.Storages) == 0 {
		return params.ErrorResults{}, nil
	}

	serverErr := func(err error) params.ErrorResult {
		if errors.IsNotFound(err) {
			err = common.ErrPerm
		}
		return params.ErrorResult{Error: common.ServerError(err)}
	}

	paramsToState := func(p params.StorageConstraints) state.StorageConstraints {
		s := state.StorageConstraints{Pool: p.Pool}
		if p.Size != nil {
			s.Size = *p.Size
		}
		if p.Count != nil {
			s.Count = *p.Count
		}
		return s
	}

	result := make([]params.ErrorResult, len(args.Storages))
	for i, one := range args.Storages {
		u, err := names.ParseUnitTag(one.UnitTag)
		if err != nil {
			result[i] = serverErr(
				errors.Annotatef(err, "parsing unit tag %v", one.UnitTag))
			continue
		}

		err = a.storage.AddStorageForUnit(u,
			one.StorageName,
			paramsToState(one.Constraints))
		if err != nil {
			result[i] = serverErr(
				errors.Annotatef(err, "adding storage %v for %v", one.StorageName, one.UnitTag))
		}
	}
	return params.ErrorResults{Results: result}, nil
}
예제 #13
0
// EnsureAvailabilitySingle applies a single StateServersSpec specification to the current environment.
// Exported so it can be called by the legacy client API in the client package.
func EnsureAvailabilitySingle(st *state.State, spec params.StateServersSpec) (params.StateServersChanges, error) {
	if !st.IsStateServer() {
		return params.StateServersChanges{}, errors.New("unsupported with hosted environments")
	}
	// Check if changes are allowed and the command may proceed.
	blockChecker := common.NewBlockChecker(st)
	if err := blockChecker.ChangeAllowed(); err != nil {
		return params.StateServersChanges{}, errors.Trace(err)
	}
	// Validate the environment tag if present.
	if spec.EnvironTag != "" {
		tag, err := names.ParseEnvironTag(spec.EnvironTag)
		if err != nil {
			return params.StateServersChanges{}, errors.Errorf("invalid environment tag: %v", err)
		}
		if _, err := st.FindEntity(tag); err != nil {
			return params.StateServersChanges{}, err
		}
	}

	series := spec.Series
	if series == "" {
		ssi, err := st.StateServerInfo()
		if err != nil {
			return params.StateServersChanges{}, err
		}

		// We should always have at least one voting machine
		// If we *really* wanted we could just pick whatever series is
		// in the majority, but really, if we always copy the value of
		// the first one, then they'll stay in sync.
		if len(ssi.VotingMachineIds) == 0 {
			// Better than a panic()?
			return params.StateServersChanges{}, fmt.Errorf("internal error, failed to find any voting machines")
		}
		templateMachine, err := st.Machine(ssi.VotingMachineIds[0])
		if err != nil {
			return params.StateServersChanges{}, err
		}
		series = templateMachine.Series()
	}
	changes, err := st.EnsureAvailability(spec.NumStateServers, spec.Constraints, series, spec.Placement)
	if err != nil {
		return params.StateServersChanges{}, err
	}
	return stateServersChanges(changes), nil
}
예제 #14
0
// NewMachineManagerAPI creates a new server-side MachineManager API facade.
func NewMachineManagerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*MachineManagerAPI, error) {

	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	s := getState(st)
	return &MachineManagerAPI{
		st:         s,
		authorizer: authorizer,
		check:      common.NewBlockChecker(s),
	}, nil
}
예제 #15
0
파일: client.go 프로젝트: pmatulis/juju
// NewClient creates a new instance of the Client Facade.
func NewClient(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*Client, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}
	apiState := getState(st)
	urlGetter := common.NewToolsURLGetter(apiState.ModelUUID(), apiState)
	client := &Client{
		api: &API{
			stateAccessor: apiState,
			auth:          authorizer,
			resources:     resources,
			statusSetter:  common.NewStatusSetter(st, common.AuthAlways()),
			toolsFinder:   common.NewToolsFinder(st, st, urlGetter),
		},
		check: common.NewBlockChecker(st)}
	return client, nil
}
예제 #16
0
파일: tools.go 프로젝트: bac/juju
// handleUpload uploads the tools data from the reader to env storage as the specified version.
func (h *toolsUploadHandler) handleUpload(r io.Reader, toolsVersions []version.Binary, serverRoot string, st *state.State) (*tools.Tools, error) {
	// Check if changes are allowed and the command may proceed.
	blockChecker := common.NewBlockChecker(st)
	if err := blockChecker.ChangeAllowed(); err != nil {
		return nil, errors.Trace(err)
	}
	storage, err := st.ToolsStorage()
	if err != nil {
		return nil, err
	}
	defer storage.Close()

	// Read the tools tarball from the request, calculating the sha256 along the way.
	data, sha256, err := readAndHash(r)
	if err != nil {
		return nil, err
	}
	if len(data) == 0 {
		return nil, errors.BadRequestf("no tools uploaded")
	}

	// TODO(wallyworld): check integrity of tools tarball.

	// Store tools and metadata in tools storage.
	for _, v := range toolsVersions {
		metadata := binarystorage.Metadata{
			Version: v.String(),
			Size:    int64(len(data)),
			SHA256:  sha256,
		}
		logger.Debugf("uploading tools %+v to storage", metadata)
		if err := storage.Add(bytes.NewReader(data), metadata); err != nil {
			return nil, err
		}
	}

	tools := &tools.Tools{
		Version: toolsVersions[0],
		Size:    int64(len(data)),
		SHA256:  sha256,
		URL:     common.ToolsURL(serverRoot, toolsVersions[0]),
	}
	return tools, nil
}
예제 #17
0
파일: keymanager.go 프로젝트: imoapps/juju
// NewKeyManagerAPI creates a new server-side keyupdater API end point.
func NewKeyManagerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*KeyManagerAPI, error) {
	// Only clients and environment managers can access the key manager service.
	if !authorizer.AuthClient() && !authorizer.AuthEnvironManager() {
		return nil, common.ErrPerm
	}
	env, err := st.Environment()
	if err != nil {
		return nil, errors.Trace(err)
	}
	// For gccgo interface comparisons, we need a Tag.
	owner := names.Tag(env.Owner())
	// TODO(wallyworld) - replace stub with real canRead function
	// For now, only admins can read authorised ssh keys.
	canRead := func(user string) bool {
		// Are we a machine agent operating as the system identity?
		if user == config.JujuSystemKey {
			_, ismachinetag := authorizer.GetAuthTag().(names.MachineTag)
			return ismachinetag
		}
		return authorizer.GetAuthTag() == owner
	}
	// TODO(wallyworld) - replace stub with real canWrite function
	// For now, only admins can write authorised ssh keys for users.
	// Machine agents can write the juju-system-key.
	canWrite := func(user string) bool {
		// Are we a machine agent writing the Juju system key.
		if user == config.JujuSystemKey {
			_, ismachinetag := authorizer.GetAuthTag().(names.MachineTag)
			return ismachinetag
		}
		// No point looking to see if the user exists as we are not
		// yet storing keys on the user.
		return authorizer.GetAuthTag() == owner
	}
	return &KeyManagerAPI{
		state:      st,
		resources:  resources,
		authorizer: authorizer,
		canRead:    canRead,
		canWrite:   canWrite,
		check:      common.NewBlockChecker(st),
	}, nil
}
예제 #18
0
파일: usermanager.go 프로젝트: makyo/juju
func NewUserManagerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*UserManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	// Since we know this is a user tag (because AuthClient is true),
	// we just do the type assertion to the UserTag.
	apiUser, _ := authorizer.GetAuthTag().(names.UserTag)
	// Pretty much all of the user manager methods have special casing for admin
	// users, so look once when we start and remember if the user is an admin.
	isAdmin, err := st.IsControllerAdministrator(apiUser)
	if err != nil {
		return nil, errors.Trace(err)
	}

	resource, ok := resources.Get("createLocalLoginMacaroon").(common.ValueResource)
	if !ok {
		return nil, errors.NotFoundf("userAuth resource")
	}
	createLocalLoginMacaroon, ok := resource.Value.(func(names.UserTag) (*macaroon.Macaroon, error))
	if !ok {
		return nil, errors.NotValidf("userAuth resource")
	}

	return &UserManagerAPI{
		state:                    st,
		authorizer:               authorizer,
		createLocalLoginMacaroon: createLocalLoginMacaroon,
		check:   common.NewBlockChecker(st),
		apiUser: apiUser,
		isAdmin: isAdmin,
	}, nil
}
예제 #19
0
파일: client_test.go 프로젝트: bac/juju
func (s *serverSuite) SetUpTest(c *gc.C) {
	s.ConfigAttrs = map[string]interface{}{
		"authorized-keys": coretesting.FakeAuthKeys,
	}
	s.baseSuite.SetUpTest(c)

	var err error
	auth := testing.FakeAuthorizer{
		Tag:            s.AdminUserTag(c),
		EnvironManager: true,
	}
	urlGetter := common.NewToolsURLGetter(s.State.ModelUUID(), s.State)
	configGetter := stateenvirons.EnvironConfigGetter{s.State}
	statusSetter := common.NewStatusSetter(s.State, common.AuthAlways())
	toolsFinder := common.NewToolsFinder(configGetter, s.State, urlGetter)
	s.newEnviron = func() (environs.Environ, error) {
		return environs.GetEnviron(configGetter, environs.New)
	}
	newEnviron := func() (environs.Environ, error) {
		return s.newEnviron()
	}
	blockChecker := common.NewBlockChecker(s.State)
	modelConfigAPI, err := modelconfig.NewModelConfigAPI(s.State, auth)
	c.Assert(err, jc.ErrorIsNil)
	s.client, err = client.NewClient(
		client.NewStateBackend(s.State),
		modelConfigAPI,
		common.NewResources(),
		auth,
		statusSetter,
		toolsFinder,
		newEnviron,
		blockChecker,
	)
	c.Assert(err, jc.ErrorIsNil)
}
예제 #20
0
파일: client.go 프로젝트: bac/juju
func newClient(st *state.State, resources facade.Resources, authorizer facade.Authorizer) (*Client, error) {
	urlGetter := common.NewToolsURLGetter(st.ModelUUID(), st)
	configGetter := stateenvirons.EnvironConfigGetter{st}
	statusSetter := common.NewStatusSetter(st, common.AuthAlways())
	toolsFinder := common.NewToolsFinder(configGetter, st, urlGetter)
	newEnviron := func() (environs.Environ, error) {
		return environs.GetEnviron(configGetter, environs.New)
	}
	blockChecker := common.NewBlockChecker(st)
	modelConfigAPI, err := modelconfig.NewModelConfigAPI(st, authorizer)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return NewClient(
		NewStateBackend(st),
		modelConfigAPI,
		resources,
		authorizer,
		statusSetter,
		toolsFinder,
		newEnviron,
		blockChecker,
	)
}
예제 #21
0
// EnableHASingle applies a single ControllersServersSpec specification to the current environment.
// Exported so it can be called by the legacy client API in the client package.
func EnableHASingle(st *state.State, spec params.ControllersSpec) (params.ControllersChanges, error) {
	if !st.IsController() {
		return params.ControllersChanges{}, errors.New("unsupported with hosted models")
	}
	// Check if changes are allowed and the command may proceed.
	blockChecker := common.NewBlockChecker(st)
	if err := blockChecker.ChangeAllowed(); err != nil {
		return params.ControllersChanges{}, errors.Trace(err)
	}
	// Validate the environment tag if present.
	if spec.ModelTag != "" {
		tag, err := names.ParseModelTag(spec.ModelTag)
		if err != nil {
			return params.ControllersChanges{}, errors.Errorf("invalid model tag: %v", err)
		}
		if _, err := st.FindEntity(tag); err != nil {
			return params.ControllersChanges{}, err
		}
	}

	series := spec.Series
	if series == "" {
		ssi, err := st.ControllerInfo()
		if err != nil {
			return params.ControllersChanges{}, err
		}

		// We should always have at least one voting machine
		// If we *really* wanted we could just pick whatever series is
		// in the majority, but really, if we always copy the value of
		// the first one, then they'll stay in sync.
		if len(ssi.VotingMachineIds) == 0 {
			// Better than a panic()?
			return params.ControllersChanges{}, errors.Errorf("internal error, failed to find any voting machines")
		}
		templateMachine, err := st.Machine(ssi.VotingMachineIds[0])
		if err != nil {
			return params.ControllersChanges{}, err
		}
		series = templateMachine.Series()
	}
	if constraints.IsEmpty(&spec.Constraints) {
		// No constraints specified, so we'll use the constraints off
		// a running controller.
		controllerInfo, err := st.ControllerInfo()
		if err != nil {
			return params.ControllersChanges{}, err
		}
		// We'll sort the controller ids to find the smallest.
		// This will typically give the initial bootstrap machine.
		var controllerIds []int
		for _, id := range controllerInfo.MachineIds {
			idNum, err := strconv.Atoi(id)
			if err != nil {
				logger.Warningf("ignoring non numeric controller id %v", id)
				continue
			}
			controllerIds = append(controllerIds, idNum)
		}
		if len(controllerIds) == 0 {
			errors.Errorf("internal error, failed to find any controllers")
		}
		sort.Ints(controllerIds)

		// Load the controller machine and get its constraints.
		controllerId := controllerIds[0]
		controller, err := st.Machine(strconv.Itoa(controllerId))
		if err != nil {
			return params.ControllersChanges{}, errors.Annotatef(err, "reading controller id %v", controllerId)
		}
		spec.Constraints, err = controller.Constraints()
		if err != nil {
			return params.ControllersChanges{}, errors.Annotatef(err, "reading constraints for controller id %v", controllerId)
		}
	}

	changes, err := st.EnableHA(spec.NumControllers, spec.Constraints, series, spec.Placement)
	if err != nil {
		return params.ControllersChanges{}, err
	}
	return controllersChanges(changes), nil
}