1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
6
"launchpad.net/juju-core/names"
7
"launchpad.net/juju-core/state"
8
"launchpad.net/juju-core/state/api/params"
9
"launchpad.net/juju-core/state/apiserver/common"
12
// FirewallerAPI provides access to the Firewaller API facade.
13
type FirewallerAPI struct {
15
*common.EnvironWatcher
16
*common.AgentEntityWatcher
18
*common.EnvironMachinesWatcher
19
*common.InstanceIdGetter
22
resources *common.Resources
23
authorizer common.Authorizer
24
accessUnit common.GetAuthFunc
25
accessService common.GetAuthFunc
28
// NewFirewallerAPI creates a new server-side FirewallerAPI facade.
29
func NewFirewallerAPI(
31
resources *common.Resources,
32
authorizer common.Authorizer,
33
) (*FirewallerAPI, error) {
34
if !authorizer.AuthEnvironManager() {
35
// Firewaller must run as environment manager.
36
return nil, common.ErrPerm
38
// Set up the various authorization checkers.
39
accessUnit := getAuthFuncForTagKind(names.UnitTagKind)
40
accessService := getAuthFuncForTagKind(names.ServiceTagKind)
41
accessMachine := getAuthFuncForTagKind(names.MachineTagKind)
42
accessEnviron := getAuthFuncForTagKind("")
43
accessUnitOrService := common.AuthEither(accessUnit, accessService)
44
accessUnitServiceOrMachine := common.AuthEither(accessUnitOrService, accessMachine)
46
// Life() is supported for units, services or machines.
47
lifeGetter := common.NewLifeGetter(
49
accessUnitServiceOrMachine,
51
// EnvironConfig() and WatchForEnvironConfigChanges() are allowed
52
// with unrestriced access.
53
environWatcher := common.NewEnvironWatcher(
59
// Watch() is supported for units or services.
60
entityWatcher := common.NewAgentEntityWatcher(
65
// WatchUnits() is supported for machines.
66
unitsWatcher := common.NewUnitsWatcher(st,
70
// WatchEnvironMachines() is allowed with unrestricted access.
71
machinesWatcher := common.NewEnvironMachinesWatcher(
76
// InstanceId() is supported for machines.
77
instanceIdGetter := common.NewInstanceIdGetter(
81
return &FirewallerAPI{
82
LifeGetter: lifeGetter,
83
EnvironWatcher: environWatcher,
84
AgentEntityWatcher: entityWatcher,
85
UnitsWatcher: unitsWatcher,
86
EnvironMachinesWatcher: machinesWatcher,
87
InstanceIdGetter: instanceIdGetter,
90
authorizer: authorizer,
91
accessUnit: accessUnit,
92
accessService: accessService,
96
// OpenedPorts returns the list of opened ports for each given unit.
97
func (f *FirewallerAPI) OpenedPorts(args params.Entities) (params.PortsResults, error) {
98
result := params.PortsResults{
99
Results: make([]params.PortsResult, len(args.Entities)),
101
canAccess, err := f.accessUnit()
103
return params.PortsResults{}, err
105
for i, entity := range args.Entities {
107
unit, err = f.getUnit(canAccess, entity.Tag)
109
result.Results[i].Ports = unit.OpenedPorts()
111
result.Results[i].Error = common.ServerError(err)
116
// GetExposed returns the exposed flag value for each given service.
117
func (f *FirewallerAPI) GetExposed(args params.Entities) (params.BoolResults, error) {
118
result := params.BoolResults{
119
Results: make([]params.BoolResult, len(args.Entities)),
121
canAccess, err := f.accessService()
123
return params.BoolResults{}, err
125
for i, entity := range args.Entities {
126
var service *state.Service
127
service, err = f.getService(canAccess, entity.Tag)
129
result.Results[i].Result = service.IsExposed()
131
result.Results[i].Error = common.ServerError(err)
136
// GetAssignedMachine returns the assigned machine tag (if any) for
138
func (f *FirewallerAPI) GetAssignedMachine(args params.Entities) (params.StringResults, error) {
139
result := params.StringResults{
140
Results: make([]params.StringResult, len(args.Entities)),
142
canAccess, err := f.accessUnit()
144
return params.StringResults{}, err
146
for i, entity := range args.Entities {
148
unit, err = f.getUnit(canAccess, entity.Tag)
151
machineId, err = unit.AssignedMachineId()
153
result.Results[i].Result = names.MachineTag(machineId)
156
result.Results[i].Error = common.ServerError(err)
161
func (f *FirewallerAPI) getEntity(canAccess common.AuthFunc, tag string) (state.Entity, error) {
163
return nil, common.ErrPerm
165
return f.st.FindEntity(tag)
168
func (f *FirewallerAPI) getUnit(canAccess common.AuthFunc, tag string) (*state.Unit, error) {
169
entity, err := f.getEntity(canAccess, tag)
173
// The authorization function guarantees that the tag represents a
175
return entity.(*state.Unit), nil
178
func (f *FirewallerAPI) getService(canAccess common.AuthFunc, tag string) (*state.Service, error) {
179
entity, err := f.getEntity(canAccess, tag)
183
// The authorization function guarantees that the tag represents a
185
return entity.(*state.Service), nil
188
// getAuthFuncForTagKind returns a GetAuthFunc which creates an
189
// AuthFunc allowing only the given tag kind and denies all
190
// others. In the special case where a single empty string is given,
191
// it's assumed only environment tags are allowed, but not specified
193
func getAuthFuncForTagKind(kind string) common.GetAuthFunc {
194
return func() (common.AuthFunc, error) {
195
return func(tag string) bool {
197
// Assume an empty tag means a missing environment tag.
200
// Allow only the given tag kind.
201
_, _, err := names.ParseTag(tag, kind)