~rogpeppe/juju-core/themue-058-debug-log-api

« back to all changes in this revision

Viewing changes to state/apiserver/firewaller/firewaller.go

  • Committer: Frank Mueller
  • Date: 2014-01-23 14:14:49 UTC
  • mfrom: (2152.1.95 juju-core)
  • Revision ID: frank.mueller@canonical.com-20140123141449-b30l57y7gs3wjkpw
debugger: merged trunk and fixed permission and interface problems

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012, 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
package firewaller
 
4
 
 
5
import (
 
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"
 
10
)
 
11
 
 
12
// FirewallerAPI provides access to the Firewaller API facade.
 
13
type FirewallerAPI struct {
 
14
        *common.LifeGetter
 
15
        *common.EnvironWatcher
 
16
        *common.AgentEntityWatcher
 
17
        *common.UnitsWatcher
 
18
        *common.EnvironMachinesWatcher
 
19
        *common.InstanceIdGetter
 
20
 
 
21
        st            *state.State
 
22
        resources     *common.Resources
 
23
        authorizer    common.Authorizer
 
24
        accessUnit    common.GetAuthFunc
 
25
        accessService common.GetAuthFunc
 
26
}
 
27
 
 
28
// NewFirewallerAPI creates a new server-side FirewallerAPI facade.
 
29
func NewFirewallerAPI(
 
30
        st *state.State,
 
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
 
37
        }
 
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)
 
45
 
 
46
        // Life() is supported for units, services or machines.
 
47
        lifeGetter := common.NewLifeGetter(
 
48
                st,
 
49
                accessUnitServiceOrMachine,
 
50
        )
 
51
        // EnvironConfig() and WatchForEnvironConfigChanges() are allowed
 
52
        // with unrestriced access.
 
53
        environWatcher := common.NewEnvironWatcher(
 
54
                st,
 
55
                resources,
 
56
                accessEnviron,
 
57
                accessEnviron,
 
58
        )
 
59
        // Watch() is supported for units or services.
 
60
        entityWatcher := common.NewAgentEntityWatcher(
 
61
                st,
 
62
                resources,
 
63
                accessUnitOrService,
 
64
        )
 
65
        // WatchUnits() is supported for machines.
 
66
        unitsWatcher := common.NewUnitsWatcher(st,
 
67
                resources,
 
68
                accessMachine,
 
69
        )
 
70
        // WatchEnvironMachines() is allowed with unrestricted access.
 
71
        machinesWatcher := common.NewEnvironMachinesWatcher(
 
72
                st,
 
73
                resources,
 
74
                accessEnviron,
 
75
        )
 
76
        // InstanceId() is supported for machines.
 
77
        instanceIdGetter := common.NewInstanceIdGetter(
 
78
                st,
 
79
                accessMachine,
 
80
        )
 
81
        return &FirewallerAPI{
 
82
                LifeGetter:             lifeGetter,
 
83
                EnvironWatcher:         environWatcher,
 
84
                AgentEntityWatcher:     entityWatcher,
 
85
                UnitsWatcher:           unitsWatcher,
 
86
                EnvironMachinesWatcher: machinesWatcher,
 
87
                InstanceIdGetter:       instanceIdGetter,
 
88
                st:                     st,
 
89
                resources:              resources,
 
90
                authorizer:             authorizer,
 
91
                accessUnit:             accessUnit,
 
92
                accessService:          accessService,
 
93
        }, nil
 
94
}
 
95
 
 
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)),
 
100
        }
 
101
        canAccess, err := f.accessUnit()
 
102
        if err != nil {
 
103
                return params.PortsResults{}, err
 
104
        }
 
105
        for i, entity := range args.Entities {
 
106
                var unit *state.Unit
 
107
                unit, err = f.getUnit(canAccess, entity.Tag)
 
108
                if err == nil {
 
109
                        result.Results[i].Ports = unit.OpenedPorts()
 
110
                }
 
111
                result.Results[i].Error = common.ServerError(err)
 
112
        }
 
113
        return result, nil
 
114
}
 
115
 
 
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)),
 
120
        }
 
121
        canAccess, err := f.accessService()
 
122
        if err != nil {
 
123
                return params.BoolResults{}, err
 
124
        }
 
125
        for i, entity := range args.Entities {
 
126
                var service *state.Service
 
127
                service, err = f.getService(canAccess, entity.Tag)
 
128
                if err == nil {
 
129
                        result.Results[i].Result = service.IsExposed()
 
130
                }
 
131
                result.Results[i].Error = common.ServerError(err)
 
132
        }
 
133
        return result, nil
 
134
}
 
135
 
 
136
// GetAssignedMachine returns the assigned machine tag (if any) for
 
137
// each given unit.
 
138
func (f *FirewallerAPI) GetAssignedMachine(args params.Entities) (params.StringResults, error) {
 
139
        result := params.StringResults{
 
140
                Results: make([]params.StringResult, len(args.Entities)),
 
141
        }
 
142
        canAccess, err := f.accessUnit()
 
143
        if err != nil {
 
144
                return params.StringResults{}, err
 
145
        }
 
146
        for i, entity := range args.Entities {
 
147
                var unit *state.Unit
 
148
                unit, err = f.getUnit(canAccess, entity.Tag)
 
149
                if err == nil {
 
150
                        var machineId string
 
151
                        machineId, err = unit.AssignedMachineId()
 
152
                        if err == nil {
 
153
                                result.Results[i].Result = names.MachineTag(machineId)
 
154
                        }
 
155
                }
 
156
                result.Results[i].Error = common.ServerError(err)
 
157
        }
 
158
        return result, nil
 
159
}
 
160
 
 
161
func (f *FirewallerAPI) getEntity(canAccess common.AuthFunc, tag string) (state.Entity, error) {
 
162
        if !canAccess(tag) {
 
163
                return nil, common.ErrPerm
 
164
        }
 
165
        return f.st.FindEntity(tag)
 
166
}
 
167
 
 
168
func (f *FirewallerAPI) getUnit(canAccess common.AuthFunc, tag string) (*state.Unit, error) {
 
169
        entity, err := f.getEntity(canAccess, tag)
 
170
        if err != nil {
 
171
                return nil, err
 
172
        }
 
173
        // The authorization function guarantees that the tag represents a
 
174
        // unit.
 
175
        return entity.(*state.Unit), nil
 
176
}
 
177
 
 
178
func (f *FirewallerAPI) getService(canAccess common.AuthFunc, tag string) (*state.Service, error) {
 
179
        entity, err := f.getEntity(canAccess, tag)
 
180
        if err != nil {
 
181
                return nil, err
 
182
        }
 
183
        // The authorization function guarantees that the tag represents a
 
184
        // service.
 
185
        return entity.(*state.Service), nil
 
186
}
 
187
 
 
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
 
192
// (for now).
 
193
func getAuthFuncForTagKind(kind string) common.GetAuthFunc {
 
194
        return func() (common.AuthFunc, error) {
 
195
                return func(tag string) bool {
 
196
                        if tag == "" {
 
197
                                // Assume an empty tag means a missing environment tag.
 
198
                                return kind == ""
 
199
                        }
 
200
                        // Allow only the given tag kind.
 
201
                        _, _, err := names.ParseTag(tag, kind)
 
202
                        if err != nil {
 
203
                                return false
 
204
                        }
 
205
                        return true
 
206
                }, nil
 
207
        }
 
208
}