~juju-qa/ubuntu/yakkety/juju/2.0-rc3-again

« back to all changes in this revision

Viewing changes to src/launchpad.net/goamz/iam/iam.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-04-24 22:34:47 UTC
  • Revision ID: package-import@ubuntu.com-20130424223447-f0qdji7ubnyo0s71
Tags: upstream-1.10.0.1
ImportĀ upstreamĀ versionĀ 1.10.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// The iam package provides types and functions for interaction with the AWS
 
2
// Identity and Access Management (IAM) service.
 
3
package iam
 
4
 
 
5
import (
 
6
        "encoding/xml"
 
7
        "launchpad.net/goamz/aws"
 
8
        "net/http"
 
9
        "net/url"
 
10
        "strconv"
 
11
        "strings"
 
12
        "time"
 
13
)
 
14
 
 
15
// The IAM type encapsulates operations operations with the IAM endpoint.
 
16
type IAM struct {
 
17
        aws.Auth
 
18
        aws.Region
 
19
}
 
20
 
 
21
// New creates a new IAM instance.
 
22
func New(auth aws.Auth, region aws.Region) *IAM {
 
23
        return &IAM{auth, region}
 
24
}
 
25
 
 
26
func (iam *IAM) query(params map[string]string, resp interface{}) error {
 
27
        params["Version"] = "2010-05-08"
 
28
        params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
 
29
        endpoint, err := url.Parse(iam.IAMEndpoint)
 
30
        if err != nil {
 
31
                return err
 
32
        }
 
33
        sign(iam.Auth, "GET", "/", params, endpoint.Host)
 
34
        endpoint.RawQuery = multimap(params).Encode()
 
35
        r, err := http.Get(endpoint.String())
 
36
        if err != nil {
 
37
                return err
 
38
        }
 
39
        defer r.Body.Close()
 
40
        if r.StatusCode > 200 {
 
41
                return buildError(r)
 
42
        }
 
43
        return xml.NewDecoder(r.Body).Decode(resp)
 
44
}
 
45
 
 
46
func (iam *IAM) postQuery(params map[string]string, resp interface{}) error {
 
47
        endpoint, err := url.Parse(iam.IAMEndpoint)
 
48
        if err != nil {
 
49
                return err
 
50
        }
 
51
        params["Version"] = "2010-05-08"
 
52
        params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
 
53
        sign(iam.Auth, "POST", "/", params, endpoint.Host)
 
54
        encoded := multimap(params).Encode()
 
55
        body := strings.NewReader(encoded)
 
56
        req, err := http.NewRequest("POST", endpoint.String(), body)
 
57
        if err != nil {
 
58
                return err
 
59
        }
 
60
        req.Header.Set("Host", endpoint.Host)
 
61
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 
62
        req.Header.Set("Content-Length", strconv.Itoa(len(encoded)))
 
63
        r, err := http.DefaultClient.Do(req)
 
64
        if err != nil {
 
65
                return err
 
66
        }
 
67
        defer r.Body.Close()
 
68
        if r.StatusCode > 200 {
 
69
                return buildError(r)
 
70
        }
 
71
        return xml.NewDecoder(r.Body).Decode(resp)
 
72
}
 
73
 
 
74
func buildError(r *http.Response) error {
 
75
        var (
 
76
                err    Error
 
77
                errors xmlErrors
 
78
        )
 
79
        xml.NewDecoder(r.Body).Decode(&errors)
 
80
        if len(errors.Errors) > 0 {
 
81
                err = errors.Errors[0]
 
82
        }
 
83
        err.StatusCode = r.StatusCode
 
84
        if err.Message == "" {
 
85
                err.Message = r.Status
 
86
        }
 
87
        return &err
 
88
}
 
89
 
 
90
func multimap(p map[string]string) url.Values {
 
91
        q := make(url.Values, len(p))
 
92
        for k, v := range p {
 
93
                q[k] = []string{v}
 
94
        }
 
95
        return q
 
96
}
 
97
 
 
98
// Response to a CreateUser request.
 
99
//
 
100
// See http://goo.gl/JS9Gz for more details.
 
101
type CreateUserResp struct {
 
102
        RequestId string `xml:"ResponseMetadata>RequestId"`
 
103
        User      User   `xml:"CreateUserResult>User"`
 
104
}
 
105
 
 
106
// User encapsulates a user managed by IAM.
 
107
//
 
108
// See http://goo.gl/BwIQ3 for more details.
 
109
type User struct {
 
110
        Arn  string
 
111
        Path string
 
112
        Id   string `xml:"UserId"`
 
113
        Name string `xml:"UserName"`
 
114
}
 
115
 
 
116
// CreateUser creates a new user in IAM.
 
117
//
 
118
// See http://goo.gl/JS9Gz for more details.
 
119
func (iam *IAM) CreateUser(name, path string) (*CreateUserResp, error) {
 
120
        params := map[string]string{
 
121
                "Action":   "CreateUser",
 
122
                "Path":     path,
 
123
                "UserName": name,
 
124
        }
 
125
        resp := new(CreateUserResp)
 
126
        if err := iam.query(params, resp); err != nil {
 
127
                return nil, err
 
128
        }
 
129
        return resp, nil
 
130
}
 
131
 
 
132
// Response for GetUser requests.
 
133
//
 
134
// See http://goo.gl/ZnzRN for more details.
 
135
type GetUserResp struct {
 
136
        RequestId string `xml:"ResponseMetadata>RequestId"`
 
137
        User      User   `xml:"GetUserResult>User"`
 
138
}
 
139
 
 
140
// GetUser gets a user from IAM.
 
141
//
 
142
// See http://goo.gl/ZnzRN for more details.
 
143
func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
 
144
        params := map[string]string{
 
145
                "Action":   "GetUser",
 
146
                "UserName": name,
 
147
        }
 
148
        resp := new(GetUserResp)
 
149
        if err := iam.query(params, resp); err != nil {
 
150
                return nil, err
 
151
        }
 
152
        return resp, nil
 
153
}
 
154
 
 
155
// DeleteUser deletes a user from IAM.
 
156
//
 
157
// See http://goo.gl/jBuCG for more details.
 
158
func (iam *IAM) DeleteUser(name string) (*SimpleResp, error) {
 
159
        params := map[string]string{
 
160
                "Action":   "DeleteUser",
 
161
                "UserName": name,
 
162
        }
 
163
        resp := new(SimpleResp)
 
164
        if err := iam.query(params, resp); err != nil {
 
165
                return nil, err
 
166
        }
 
167
        return resp, nil
 
168
}
 
169
 
 
170
// Response to a CreateGroup request.
 
171
//
 
172
// See http://goo.gl/n7NNQ for more details.
 
173
type CreateGroupResp struct {
 
174
        Group     Group  `xml:"CreateGroupResult>Group"`
 
175
        RequestId string `xml:"ResponseMetadata>RequestId"`
 
176
}
 
177
 
 
178
// Group encapsulates a group managed by IAM.
 
179
//
 
180
// See http://goo.gl/ae7Vs for more details.
 
181
type Group struct {
 
182
        Arn  string
 
183
        Id   string `xml:"GroupId"`
 
184
        Name string `xml:"GroupName"`
 
185
        Path string
 
186
}
 
187
 
 
188
// CreateGroup creates a new group in IAM.
 
189
//
 
190
// The path parameter can be used to identify which division or part of the
 
191
// organization the user belongs to.
 
192
//
 
193
// If path is unset ("") it defaults to "/".
 
194
//
 
195
// See http://goo.gl/n7NNQ for more details.
 
196
func (iam *IAM) CreateGroup(name string, path string) (*CreateGroupResp, error) {
 
197
        params := map[string]string{
 
198
                "Action":    "CreateGroup",
 
199
                "GroupName": name,
 
200
        }
 
201
        if path != "" {
 
202
                params["Path"] = path
 
203
        }
 
204
        resp := new(CreateGroupResp)
 
205
        if err := iam.query(params, resp); err != nil {
 
206
                return nil, err
 
207
        }
 
208
        return resp, nil
 
209
}
 
210
 
 
211
// Response to a ListGroups request.
 
212
//
 
213
// See http://goo.gl/W2TRj for more details.
 
214
type GroupsResp struct {
 
215
        Groups    []Group `xml:"ListGroupsResult>Groups>member"`
 
216
        RequestId string  `xml:"ResponseMetadata>RequestId"`
 
217
}
 
218
 
 
219
// Groups list the groups that have the specified path prefix.
 
220
//
 
221
// The parameter pathPrefix is optional. If pathPrefix is "", all groups are
 
222
// returned.
 
223
//
 
224
// See http://goo.gl/W2TRj for more details.
 
225
func (iam *IAM) Groups(pathPrefix string) (*GroupsResp, error) {
 
226
        params := map[string]string{
 
227
                "Action": "ListGroups",
 
228
        }
 
229
        if pathPrefix != "" {
 
230
                params["PathPrefix"] = pathPrefix
 
231
        }
 
232
        resp := new(GroupsResp)
 
233
        if err := iam.query(params, resp); err != nil {
 
234
                return nil, err
 
235
        }
 
236
        return resp, nil
 
237
}
 
238
 
 
239
// DeleteGroup deletes a group from IAM.
 
240
//
 
241
// See http://goo.gl/d5i2i for more details.
 
242
func (iam *IAM) DeleteGroup(name string) (*SimpleResp, error) {
 
243
        params := map[string]string{
 
244
                "Action":    "DeleteGroup",
 
245
                "GroupName": name,
 
246
        }
 
247
        resp := new(SimpleResp)
 
248
        if err := iam.query(params, resp); err != nil {
 
249
                return nil, err
 
250
        }
 
251
        return resp, nil
 
252
}
 
253
 
 
254
// Response to a CreateAccessKey request.
 
255
//
 
256
// See http://goo.gl/L46Py for more details.
 
257
type CreateAccessKeyResp struct {
 
258
        RequestId string    `xml:"ResponseMetadata>RequestId"`
 
259
        AccessKey AccessKey `xml:"CreateAccessKeyResult>AccessKey"`
 
260
}
 
261
 
 
262
// AccessKey encapsulates an access key generated for a user.
 
263
//
 
264
// See http://goo.gl/LHgZR for more details.
 
265
type AccessKey struct {
 
266
        UserName string
 
267
        Id       string `xml:"AccessKeyId"`
 
268
        Secret   string `xml:"SecretAccessKey,omitempty"`
 
269
        Status   string
 
270
}
 
271
 
 
272
// CreateAccessKey creates a new access key in IAM.
 
273
//
 
274
// See http://goo.gl/L46Py for more details.
 
275
func (iam *IAM) CreateAccessKey(userName string) (*CreateAccessKeyResp, error) {
 
276
        params := map[string]string{
 
277
                "Action":   "CreateAccessKey",
 
278
                "UserName": userName,
 
279
        }
 
280
        resp := new(CreateAccessKeyResp)
 
281
        if err := iam.query(params, resp); err != nil {
 
282
                return nil, err
 
283
        }
 
284
        return resp, nil
 
285
}
 
286
 
 
287
// Response to AccessKeys request.
 
288
//
 
289
// See http://goo.gl/Vjozx for more details.
 
290
type AccessKeysResp struct {
 
291
        RequestId  string      `xml:"ResponseMetadata>RequestId"`
 
292
        AccessKeys []AccessKey `xml:"ListAccessKeysResult>AccessKeyMetadata>member"`
 
293
}
 
294
 
 
295
// AccessKeys lists all acccess keys associated with a user.
 
296
//
 
297
// The userName parameter is optional. If set to "", the userName is determined
 
298
// implicitly based on the AWS Access Key ID used to sign the request.
 
299
//
 
300
// See http://goo.gl/Vjozx for more details.
 
301
func (iam *IAM) AccessKeys(userName string) (*AccessKeysResp, error) {
 
302
        params := map[string]string{
 
303
                "Action": "ListAccessKeys",
 
304
        }
 
305
        if userName != "" {
 
306
                params["UserName"] = userName
 
307
        }
 
308
        resp := new(AccessKeysResp)
 
309
        if err := iam.query(params, resp); err != nil {
 
310
                return nil, err
 
311
        }
 
312
        return resp, nil
 
313
}
 
314
 
 
315
// DeleteAccessKey deletes an access key from IAM.
 
316
//
 
317
// The userName parameter is optional. If set to "", the userName is determined
 
318
// implicitly based on the AWS Access Key ID used to sign the request.
 
319
//
 
320
// See http://goo.gl/hPGhw for more details.
 
321
func (iam *IAM) DeleteAccessKey(id, userName string) (*SimpleResp, error) {
 
322
        params := map[string]string{
 
323
                "Action":      "DeleteAccessKey",
 
324
                "AccessKeyId": id,
 
325
        }
 
326
        if userName != "" {
 
327
                params["UserName"] = userName
 
328
        }
 
329
        resp := new(SimpleResp)
 
330
        if err := iam.query(params, resp); err != nil {
 
331
                return nil, err
 
332
        }
 
333
        return resp, nil
 
334
}
 
335
 
 
336
// Response to a GetUserPolicy request.
 
337
//
 
338
// See http://goo.gl/BH04O for more details.
 
339
type GetUserPolicyResp struct {
 
340
        Policy    UserPolicy `xml:"GetUserPolicyResult"`
 
341
        RequestId string     `xml:"ResponseMetadata>RequestId"`
 
342
}
 
343
 
 
344
// UserPolicy encapsulates an IAM group policy.
 
345
//
 
346
// See http://goo.gl/C7hgS for more details.
 
347
type UserPolicy struct {
 
348
        Name     string `xml:"PolicyName"`
 
349
        UserName string `xml:"UserName"`
 
350
        Document string `xml:"PolicyDocument"`
 
351
}
 
352
 
 
353
// GetUserPolicy gets a user policy in IAM.
 
354
//
 
355
// See http://goo.gl/BH04O for more details.
 
356
func (iam *IAM) GetUserPolicy(userName, policyName string) (*GetUserPolicyResp, error) {
 
357
        params := map[string]string{
 
358
                "Action":     "GetUserPolicy",
 
359
                "UserName":   userName,
 
360
                "PolicyName": policyName,
 
361
        }
 
362
        resp := new(GetUserPolicyResp)
 
363
        if err := iam.query(params, resp); err != nil {
 
364
                return nil, err
 
365
        }
 
366
        return resp, nil
 
367
        return nil, nil
 
368
}
 
369
 
 
370
// PutUserPolicy creates a user policy in IAM.
 
371
//
 
372
// See http://goo.gl/ldCO8 for more details.
 
373
func (iam *IAM) PutUserPolicy(userName, policyName, policyDocument string) (*SimpleResp, error) {
 
374
        params := map[string]string{
 
375
                "Action":         "PutUserPolicy",
 
376
                "UserName":       userName,
 
377
                "PolicyName":     policyName,
 
378
                "PolicyDocument": policyDocument,
 
379
        }
 
380
        resp := new(SimpleResp)
 
381
        if err := iam.postQuery(params, resp); err != nil {
 
382
                return nil, err
 
383
        }
 
384
        return resp, nil
 
385
}
 
386
 
 
387
// DeleteUserPolicy deletes a user policy from IAM.
 
388
//
 
389
// See http://goo.gl/7Jncn for more details.
 
390
func (iam *IAM) DeleteUserPolicy(userName, policyName string) (*SimpleResp, error) {
 
391
        params := map[string]string{
 
392
                "Action":     "DeleteUserPolicy",
 
393
                "PolicyName": policyName,
 
394
                "UserName":   userName,
 
395
        }
 
396
        resp := new(SimpleResp)
 
397
        if err := iam.query(params, resp); err != nil {
 
398
                return nil, err
 
399
        }
 
400
        return resp, nil
 
401
}
 
402
 
 
403
type SimpleResp struct {
 
404
        RequestId string `xml:"ResponseMetadata>RequestId"`
 
405
}
 
406
 
 
407
type xmlErrors struct {
 
408
        Errors []Error `xml:"Error"`
 
409
}
 
410
 
 
411
// Error encapsulates an IAM error.
 
412
type Error struct {
 
413
        // HTTP status code of the error.
 
414
        StatusCode int
 
415
 
 
416
        // AWS code of the error.
 
417
        Code string
 
418
 
 
419
        // Message explaining the error.
 
420
        Message string
 
421
}
 
422
 
 
423
func (e *Error) Error() string {
 
424
        var prefix string
 
425
        if e.Code != "" {
 
426
                prefix = e.Code + ": "
 
427
        }
 
428
        if prefix == "" && e.StatusCode > 0 {
 
429
                prefix = strconv.Itoa(e.StatusCode) + ": "
 
430
        }
 
431
        return prefix + e.Message
 
432
}