Exemplo n.º 1
0
// NewStatusAPI creates a new server-side Status setter API facade.
func NewStatusAPI(st *state.State, getCanModify common.GetAuthFunc) *StatusAPI {
	unitSetter := common.NewStatusSetter(st, getCanModify)
	unitGetter := common.NewStatusGetter(st, getCanModify)
	serviceSetter := common.NewServiceStatusSetter(st, getCanModify)
	serviceGetter := common.NewServiceStatusGetter(st, getCanModify)
	agentSetter := common.NewStatusSetter(&unitAgentFinder{st}, getCanModify)
	return &StatusAPI{
		agentSetter:   agentSetter,
		unitSetter:    unitSetter,
		unitGetter:    unitGetter,
		serviceSetter: serviceSetter,
		serviceGetter: serviceGetter,
		getCanModify:  getCanModify,
	}
}
Exemplo n.º 2
0
func newUndertakerAPI(st State, resources facade.Resources, authorizer facade.Authorizer) (*UndertakerAPI, error) {
	if !authorizer.AuthMachineAgent() || !authorizer.AuthModelManager() {
		return nil, common.ErrPerm
	}
	model, err := st.Model()
	if err != nil {
		return nil, errors.Trace(err)
	}
	getCanModifyModel := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			if st.IsController() {
				return true
			}
			// Only the agent's model can be modified.
			modelTag, ok := tag.(names.ModelTag)
			if !ok {
				return false
			}
			return modelTag.Id() == model.UUID()
		}, nil
	}
	return &UndertakerAPI{
		st:           st,
		resources:    resources,
		StatusSetter: common.NewStatusSetter(st, getCanModifyModel),
	}, nil
}
Exemplo n.º 3
0
func (s *statusSetterSuite) SetUpTest(c *gc.C) {
	s.statusBaseSuite.SetUpTest(c)

	s.setter = common.NewStatusSetter(s.State, func() (common.AuthFunc, error) {
		return s.authFunc, nil
	})
}
Exemplo n.º 4
0
Arquivo: status.go Projeto: bac/juju
// NewStatusAPI creates a new server-side Status setter API facade.
func NewStatusAPI(st *state.State, getCanModify common.GetAuthFunc) *StatusAPI {
	// TODO(fwereade): so *all* of these have exactly the same auth
	// characteristics? I think not.
	unitSetter := common.NewStatusSetter(st, getCanModify)
	unitGetter := common.NewStatusGetter(st, getCanModify)
	serviceSetter := common.NewServiceStatusSetter(st, getCanModify)
	serviceGetter := common.NewServiceStatusGetter(st, getCanModify)
	agentSetter := common.NewStatusSetter(&common.UnitAgentFinder{st}, getCanModify)
	return &StatusAPI{
		agentSetter:   agentSetter,
		unitSetter:    unitSetter,
		unitGetter:    unitGetter,
		serviceSetter: serviceSetter,
		serviceGetter: serviceGetter,
		getCanModify:  getCanModify,
	}
}
Exemplo n.º 5
0
// New returns a new unitAssigner api instance.
func New(st *state.State, res *common.Resources, _ common.Authorizer) (*API, error) {
	setter := common.NewStatusSetter(&common.UnitAgentFinder{st}, common.AuthAlways())
	return &API{
		st:           st,
		res:          res,
		statusSetter: setter,
	}, nil
}
Exemplo n.º 6
0
// NewProvisionerAPI creates a new server-side ProvisionerAPI facade.
func NewProvisionerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*ProvisionerAPI, error) {
	if !authorizer.AuthMachineAgent() && !authorizer.AuthEnvironManager() {
		return nil, common.ErrPerm
	}
	getAuthFunc := func() (common.AuthFunc, error) {
		isEnvironManager := authorizer.AuthEnvironManager()
		isMachineAgent := authorizer.AuthMachineAgent()
		authEntityTag := authorizer.GetAuthTag()

		return func(tag names.Tag) bool {
			if isMachineAgent && tag == authEntityTag {
				// A machine agent can always access its own machine.
				return true
			}
			switch tag := tag.(type) {
			case names.MachineTag:
				parentId := state.ParentId(tag.Id())
				if parentId == "" {
					// All top-level machines are accessible by the
					// environment manager.
					return isEnvironManager
				}
				// All containers with the authenticated machine as a
				// parent are accessible by it.
				// TODO(dfc) sometimes authEntity tag is nil, which is fine because nil is
				// only equal to nil, but it suggests someone is passing an authorizer
				// with a nil tag.
				return isMachineAgent && names.NewMachineTag(parentId) == authEntityTag
			default:
				return false
			}
		}, nil
	}
	env, err := st.Environment()
	if err != nil {
		return nil, err
	}
	urlGetter := common.NewToolsURLGetter(env.UUID(), st)
	return &ProvisionerAPI{
		Remover:                common.NewRemover(st, false, getAuthFunc),
		StatusSetter:           common.NewStatusSetter(st, getAuthFunc),
		StatusGetter:           common.NewStatusGetter(st, getAuthFunc),
		DeadEnsurer:            common.NewDeadEnsurer(st, getAuthFunc),
		PasswordChanger:        common.NewPasswordChanger(st, getAuthFunc),
		LifeGetter:             common.NewLifeGetter(st, getAuthFunc),
		StateAddresser:         common.NewStateAddresser(st),
		APIAddresser:           common.NewAPIAddresser(st, resources),
		EnvironWatcher:         common.NewEnvironWatcher(st, resources, authorizer),
		EnvironMachinesWatcher: common.NewEnvironMachinesWatcher(st, resources, authorizer),
		InstanceIdGetter:       common.NewInstanceIdGetter(st, getAuthFunc),
		ToolsFinder:            common.NewToolsFinder(st, st, urlGetter),
		st:                     st,
		resources:              resources,
		authorizer:             authorizer,
		getAuthFunc:            getAuthFunc,
	}, nil
}
Exemplo n.º 7
0
func (*statusSetterSuite) TestSetStatusNoArgsNoError(c *gc.C) {
	getCanModify := func() (common.AuthFunc, error) {
		return nil, fmt.Errorf("pow")
	}
	s := common.NewStatusSetter(&fakeState{}, getCanModify)
	result, err := s.SetStatus(params.SetStatus{})
	c.Assert(err, gc.IsNil)
	c.Assert(result.Results, gc.HasLen, 0)
}
Exemplo n.º 8
0
func (*statusSetterSuite) TestUpdateStatus(c *gc.C) {
	st := &fakeState{
		entities: map[names.Tag]entityWithError{
			m("0"): &fakeStatusSetter{status: params.StatusPending, info: "blah", err: fmt.Errorf("x0 fails")},
			m("1"): &fakeStatusSetter{status: params.StatusError, info: "foo", data: map[string]interface{}{"foo": "blah"}},
			m("2"): &fakeStatusSetter{status: params.StatusError, info: "some info"},
			m("3"): &fakeStatusSetter{fetchError: "x3 error"},
			m("4"): &fakeStatusSetter{status: params.StatusStarted},
			m("5"): &fakeStatusSetter{status: params.StatusStopped, info: ""},
		},
	}
	getCanModify := func() (common.AuthFunc, error) {
		x0 := m("0")
		x1 := m("1")
		x2 := m("2")
		x3 := m("3")
		x4 := m("4")
		return func(tag names.Tag) bool {
			return tag == x0 || tag == x1 || tag == x2 || tag == x3 || tag == x4
		}, nil
	}
	s := common.NewStatusSetter(st, getCanModify)
	args := params.SetStatus{
		Entities: []params.EntityStatus{
			{Tag: "machine-0", Data: nil},
			{Tag: "machine-1", Data: nil},
			{Tag: "machine-2", Data: map[string]interface{}{"foo": "bar"}},
			{Tag: "machine-3", Data: map[string]interface{}{"foo": "bar"}},
			{Tag: "machine-4", Data: map[string]interface{}{"foo": "bar"}},
			{Tag: "machine-5", Data: map[string]interface{}{"foo": "bar"}},
			{Tag: "machine-6", Data: nil},
		},
	}
	result, err := s.UpdateStatus(args)
	c.Assert(err, gc.IsNil)
	c.Assert(result, gc.DeepEquals, params.ErrorResults{
		Results: []params.ErrorResult{
			{&params.Error{Message: "x0 fails"}},
			{nil},
			{nil},
			{&params.Error{Message: "x3 error"}},
			{&params.Error{Message: `"machine-4" is not in an error state`}},
			{apiservertesting.ErrUnauthorized},
			{apiservertesting.ErrUnauthorized},
		},
	})
	get := func(tag names.Tag) *fakeStatusSetter {
		return st.entities[tag].(*fakeStatusSetter)
	}
	c.Assert(get(m("1")).status, gc.Equals, params.StatusError)
	c.Assert(get(m("1")).info, gc.Equals, "foo")
	c.Assert(get(m("1")).data, gc.DeepEquals, map[string]interface{}{"foo": "blah"})
	c.Assert(get(m("2")).status, gc.Equals, params.StatusError)
	c.Assert(get(m("2")).info, gc.Equals, "some info")
	c.Assert(get(m("2")).data, gc.DeepEquals, map[string]interface{}{"foo": "bar"})
}
Exemplo n.º 9
0
// 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
	}
	return &Client{api: &API{
		state:        st,
		auth:         authorizer,
		resources:    resources,
		statusSetter: common.NewStatusSetter(st, common.AuthAlways()),
	}}, nil
}
Exemplo n.º 10
0
func (*statusSetterSuite) TestSetStatusError(c *gc.C) {
	getCanModify := func() (common.AuthFunc, error) {
		return nil, fmt.Errorf("pow")
	}
	s := common.NewStatusSetter(&fakeState{}, getCanModify)
	args := params.SetStatus{
		Entities: []params.EntityStatus{{"x0", "", "", nil}},
	}
	_, err := s.SetStatus(args)
	c.Assert(err, gc.ErrorMatches, "pow")
}
Exemplo n.º 11
0
func (*statusSetterSuite) TestSetStatus(c *gc.C) {
	st := &fakeState{
		entities: map[names.Tag]entityWithError{
			u("x/0"): &fakeStatusSetter{status: params.StatusPending, info: "blah", err: fmt.Errorf("x0 fails")},
			u("x/1"): &fakeStatusSetter{status: params.StatusStarted, info: "foo"},
			u("x/2"): &fakeStatusSetter{status: params.StatusError, info: "some info"},
			u("x/3"): &fakeStatusSetter{fetchError: "x3 error"},
			u("x/4"): &fakeStatusSetter{status: params.StatusStopped, info: ""},
		},
	}
	getCanModify := func() (common.AuthFunc, error) {
		x0 := u("x/0")
		x1 := u("x/1")
		x2 := u("x/2")
		x3 := u("x/3")
		return func(tag names.Tag) bool {
			return tag == x0 || tag == x1 || tag == x2 || tag == x3
		}, nil
	}
	s := common.NewStatusSetter(st, getCanModify)
	args := params.SetStatus{
		Entities: []params.EntityStatus{
			{"unit-x-0", params.StatusStarted, "bar", nil},
			{"unit-x-1", params.StatusStopped, "", nil},
			{"unit-x-2", params.StatusPending, "not really", nil},
			{"unit-x-3", params.StatusStopped, "", nil},
			{"unit-x-4", params.StatusError, "blarg", nil},
			{"unit-x-5", params.StatusStarted, "42", nil},
		},
	}
	result, err := s.SetStatus(args)
	c.Assert(err, gc.IsNil)
	c.Assert(result, gc.DeepEquals, params.ErrorResults{
		Results: []params.ErrorResult{
			{&params.Error{Message: "x0 fails"}},
			{nil},
			{nil},
			{&params.Error{Message: "x3 error"}},
			{apiservertesting.ErrUnauthorized},
			{apiservertesting.ErrUnauthorized},
		},
	})
	get := func(tag names.Tag) *fakeStatusSetter {
		return st.entities[tag].(*fakeStatusSetter)
	}
	c.Assert(get(u("x/1")).status, gc.Equals, params.StatusStopped)
	c.Assert(get(u("x/1")).info, gc.Equals, "")
	c.Assert(get(u("x/2")).status, gc.Equals, params.StatusPending)
	c.Assert(get(u("x/2")).info, gc.Equals, "not really")
}
Exemplo n.º 12
0
// 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
}
Exemplo n.º 13
0
// 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
	}
	env, err := st.Environment()
	if err != nil {
		return nil, err
	}
	urlGetter := common.NewToolsURLGetter(env.UUID(), st)
	return &Client{api: &API{
		state:        st,
		auth:         authorizer,
		resources:    resources,
		statusSetter: common.NewStatusSetter(st, common.AuthAlways()),
		toolsFinder:  common.NewToolsFinder(st, st, urlGetter),
	}}, nil
}
Exemplo n.º 14
0
// 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
}
Exemplo n.º 15
0
Arquivo: deployer.go Projeto: bac/juju
// NewDeployerAPI creates a new server-side DeployerAPI facade.
func NewDeployerAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*DeployerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getAuthFunc := func() (common.AuthFunc, error) {
		// Get all units of the machine and cache them.
		thisMachineTag := authorizer.GetAuthTag()
		units, err := getAllUnits(st, thisMachineTag)
		if err != nil {
			return nil, err
		}
		// Then we just check if the unit is already known.
		return func(tag names.Tag) bool {
			for _, unit := range units {
				// TODO (thumper): remove the names.Tag conversion when gccgo
				// implements concrete-type-to-interface comparison correctly.
				if names.Tag(names.NewUnitTag(unit)) == tag {
					return true
				}
			}
			return false
		}, nil
	}
	getCanWatch := func() (common.AuthFunc, error) {
		return authorizer.AuthOwner, nil
	}
	return &DeployerAPI{
		Remover:         common.NewRemover(st, true, getAuthFunc),
		PasswordChanger: common.NewPasswordChanger(st, getAuthFunc),
		LifeGetter:      common.NewLifeGetter(st, getAuthFunc),
		StateAddresser:  common.NewStateAddresser(st),
		APIAddresser:    common.NewAPIAddresser(st, resources),
		UnitsWatcher:    common.NewUnitsWatcher(st, resources, getCanWatch),
		StatusSetter:    common.NewStatusSetter(st, getAuthFunc),
		st:              st,
		resources:       resources,
		authorizer:      authorizer,
	}, nil
}
Exemplo n.º 16
0
// NewMachinerAPI creates a new instance of the Machiner API.
func NewMachinerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*MachinerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getCanModify := func() (common.AuthFunc, error) {
		return authorizer.AuthOwner, nil
	}
	getCanRead := func() (common.AuthFunc, error) {
		return authorizer.AuthOwner, nil
	}
	return &MachinerAPI{
		LifeGetter:         common.NewLifeGetter(st, getCanRead),
		StatusSetter:       common.NewStatusSetter(st, getCanModify),
		DeadEnsurer:        common.NewDeadEnsurer(st, getCanModify),
		AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, getCanRead),
		APIAddresser:       common.NewAPIAddresser(st, resources),
		st:                 st,
		auth:               authorizer,
		getCanModify:       getCanModify,
	}, nil
}
Exemplo n.º 17
0
// NewUniterAPI creates a new instance of the Uniter API.
func NewUniterAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*UniterAPI, error) {
	if !authorizer.AuthUnitAgent() {
		return nil, common.ErrPerm
	}
	accessUnit := func() (common.AuthFunc, error) {
		return authorizer.AuthOwner, nil
	}
	accessService := func() (common.AuthFunc, error) {
		switch tag := authorizer.GetAuthTag().(type) {
		case names.UnitTag:
			entity, err := st.Unit(tag.Id())
			if err != nil {
				return nil, errors.Trace(err)
			}
			serviceName := entity.ServiceName()
			serviceTag := names.NewServiceTag(serviceName)
			return func(tag names.Tag) bool {
				return tag == serviceTag
			}, nil
		default:
			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
		}
	}
	accessUnitOrService := common.AuthEither(accessUnit, accessService)

	return &UniterAPI{
		LifeGetter:         common.NewLifeGetter(st, accessUnitOrService),
		StatusSetter:       common.NewStatusSetter(st, accessUnit),
		DeadEnsurer:        common.NewDeadEnsurer(st, accessUnit),
		AgentEntityWatcher: common.NewAgentEntityWatcher(st, resources, accessUnitOrService),
		APIAddresser:       common.NewAPIAddresser(st, resources),
		EnvironWatcher:     common.NewEnvironWatcher(st, resources, authorizer),

		st:            st,
		auth:          authorizer,
		resources:     resources,
		accessUnit:    accessUnit,
		accessService: accessService,
	}, nil
}
Exemplo n.º 18
0
Arquivo: client.go Projeto: 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,
	)
}
Exemplo n.º 19
0
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)
}
Exemplo n.º 20
0
// NewStorageProvisionerAPI creates a new server-side StorageProvisionerAPI facade.
func NewStorageProvisionerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*StorageProvisionerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	canAccessStorageMachine := func(tag names.MachineTag, allowEnvironManager bool) bool {
		authEntityTag := authorizer.GetAuthTag()
		if tag == authEntityTag {
			// Machine agents can access volumes
			// scoped to their own machine.
			return true
		}
		parentId := state.ParentId(tag.Id())
		if parentId == "" {
			return allowEnvironManager && authorizer.AuthEnvironManager()
		}
		// All containers with the authenticated
		// machine as a parent are accessible by it.
		return names.NewMachineTag(parentId) == authEntityTag
	}
	getScopeAuthFunc := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			switch tag := tag.(type) {
			case names.EnvironTag:
				// Environment managers can access all volumes
				// and filesystems scoped to the environment.
				isEnvironManager := authorizer.AuthEnvironManager()
				return isEnvironManager && tag == st.EnvironTag()
			case names.MachineTag:
				return canAccessStorageMachine(tag, false)
			default:
				return false
			}
		}, nil
	}
	canAccessStorageEntity := func(tag names.Tag, allowMachines bool) bool {
		switch tag := tag.(type) {
		case names.VolumeTag:
			machineTag, ok := names.VolumeMachine(tag)
			if ok {
				return canAccessStorageMachine(machineTag, false)
			}
			return authorizer.AuthEnvironManager()
		case names.FilesystemTag:
			machineTag, ok := names.FilesystemMachine(tag)
			if ok {
				return canAccessStorageMachine(machineTag, false)
			}
			return authorizer.AuthEnvironManager()
		case names.MachineTag:
			return allowMachines && canAccessStorageMachine(tag, true)
		default:
			return false
		}
	}
	getStorageEntityAuthFunc := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			return canAccessStorageEntity(tag, false)
		}, nil
	}
	getLifeAuthFunc := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			return canAccessStorageEntity(tag, true)
		}, nil
	}
	getAttachmentAuthFunc := func() (func(names.MachineTag, names.Tag) bool, error) {
		// getAttachmentAuthFunc returns a function that validates
		// access by the authenticated user to an attachment.
		return func(machineTag names.MachineTag, attachmentTag names.Tag) bool {
			// Machine agents can access their own machine, and
			// machines contained. Environment managers can access
			// top-level machines.
			if !canAccessStorageMachine(machineTag, true) {
				return false
			}
			// Environment managers can access environment-scoped
			// volumes and volumes scoped to their own machines.
			// Other machine agents can access volumes regardless
			// of their scope.
			if !authorizer.AuthEnvironManager() {
				return true
			}
			var machineScope names.MachineTag
			var hasMachineScope bool
			switch attachmentTag := attachmentTag.(type) {
			case names.VolumeTag:
				machineScope, hasMachineScope = names.VolumeMachine(attachmentTag)
			case names.FilesystemTag:
				machineScope, hasMachineScope = names.FilesystemMachine(attachmentTag)
			}
			return !hasMachineScope || machineScope == authorizer.GetAuthTag()
		}, nil
	}
	getMachineAuthFunc := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			if tag, ok := tag.(names.MachineTag); ok {
				return canAccessStorageMachine(tag, true)
			}
			return false
		}, nil
	}
	getBlockDevicesAuthFunc := func() (common.AuthFunc, error) {
		return func(tag names.Tag) bool {
			if tag, ok := tag.(names.MachineTag); ok {
				return canAccessStorageMachine(tag, false)
			}
			return false
		}, nil
	}
	stateInterface := getState(st)
	settings := getSettingsManager(st)
	return &StorageProvisionerAPI{
		LifeGetter:       common.NewLifeGetter(stateInterface, getLifeAuthFunc),
		DeadEnsurer:      common.NewDeadEnsurer(stateInterface, getStorageEntityAuthFunc),
		EnvironWatcher:   common.NewEnvironWatcher(stateInterface, resources, authorizer),
		InstanceIdGetter: common.NewInstanceIdGetter(st, getMachineAuthFunc),
		StatusSetter:     common.NewStatusSetter(st, getStorageEntityAuthFunc),

		st:                       stateInterface,
		settings:                 settings,
		resources:                resources,
		authorizer:               authorizer,
		getScopeAuthFunc:         getScopeAuthFunc,
		getStorageEntityAuthFunc: getStorageEntityAuthFunc,
		getAttachmentAuthFunc:    getAttachmentAuthFunc,
		getMachineAuthFunc:       getMachineAuthFunc,
		getBlockDevicesAuthFunc:  getBlockDevicesAuthFunc,
	}, nil
}