1
// The iam package provides types and functions for interaction with the AWS
2
// Identity and Access Management (IAM) service.
7
"launchpad.net/goamz/aws"
15
// The IAM type encapsulates operations operations with the IAM endpoint.
21
// New creates a new IAM instance.
22
func New(auth aws.Auth, region aws.Region) *IAM {
23
return &IAM{auth, region}
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)
33
sign(iam.Auth, "GET", "/", params, endpoint.Host)
34
endpoint.RawQuery = multimap(params).Encode()
35
r, err := http.Get(endpoint.String())
40
if r.StatusCode > 200 {
43
return xml.NewDecoder(r.Body).Decode(resp)
46
func (iam *IAM) postQuery(params map[string]string, resp interface{}) error {
47
endpoint, err := url.Parse(iam.IAMEndpoint)
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)
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)
68
if r.StatusCode > 200 {
71
return xml.NewDecoder(r.Body).Decode(resp)
74
func buildError(r *http.Response) error {
79
xml.NewDecoder(r.Body).Decode(&errors)
80
if len(errors.Errors) > 0 {
81
err = errors.Errors[0]
83
err.StatusCode = r.StatusCode
84
if err.Message == "" {
85
err.Message = r.Status
90
func multimap(p map[string]string) url.Values {
91
q := make(url.Values, len(p))
98
// Response to a CreateUser request.
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"`
106
// User encapsulates a user managed by IAM.
108
// See http://goo.gl/BwIQ3 for more details.
112
Id string `xml:"UserId"`
113
Name string `xml:"UserName"`
116
// CreateUser creates a new user in IAM.
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",
125
resp := new(CreateUserResp)
126
if err := iam.query(params, resp); err != nil {
132
// Response for GetUser requests.
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"`
140
// GetUser gets a user from IAM.
142
// See http://goo.gl/ZnzRN for more details.
143
func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
144
params := map[string]string{
148
resp := new(GetUserResp)
149
if err := iam.query(params, resp); err != nil {
155
// DeleteUser deletes a user from IAM.
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",
163
resp := new(SimpleResp)
164
if err := iam.query(params, resp); err != nil {
170
// Response to a CreateGroup request.
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"`
178
// Group encapsulates a group managed by IAM.
180
// See http://goo.gl/ae7Vs for more details.
183
Id string `xml:"GroupId"`
184
Name string `xml:"GroupName"`
188
// CreateGroup creates a new group in IAM.
190
// The path parameter can be used to identify which division or part of the
191
// organization the user belongs to.
193
// If path is unset ("") it defaults to "/".
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",
202
params["Path"] = path
204
resp := new(CreateGroupResp)
205
if err := iam.query(params, resp); err != nil {
211
// Response to a ListGroups request.
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"`
219
// Groups list the groups that have the specified path prefix.
221
// The parameter pathPrefix is optional. If pathPrefix is "", all groups are
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",
229
if pathPrefix != "" {
230
params["PathPrefix"] = pathPrefix
232
resp := new(GroupsResp)
233
if err := iam.query(params, resp); err != nil {
239
// DeleteGroup deletes a group from IAM.
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",
247
resp := new(SimpleResp)
248
if err := iam.query(params, resp); err != nil {
254
// Response to a CreateAccessKey request.
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"`
262
// AccessKey encapsulates an access key generated for a user.
264
// See http://goo.gl/LHgZR for more details.
265
type AccessKey struct {
267
Id string `xml:"AccessKeyId"`
268
Secret string `xml:"SecretAccessKey,omitempty"`
272
// CreateAccessKey creates a new access key in IAM.
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,
280
resp := new(CreateAccessKeyResp)
281
if err := iam.query(params, resp); err != nil {
287
// Response to AccessKeys request.
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"`
295
// AccessKeys lists all acccess keys associated with a user.
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.
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",
306
params["UserName"] = userName
308
resp := new(AccessKeysResp)
309
if err := iam.query(params, resp); err != nil {
315
// DeleteAccessKey deletes an access key from IAM.
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.
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",
327
params["UserName"] = userName
329
resp := new(SimpleResp)
330
if err := iam.query(params, resp); err != nil {
336
// Response to a GetUserPolicy request.
338
// See http://goo.gl/BH04O for more details.
339
type GetUserPolicyResp struct {
340
Policy UserPolicy `xml:"GetUserPolicyResult"`
341
RequestId string `xml:"ResponseMetadata>RequestId"`
344
// UserPolicy encapsulates an IAM group policy.
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"`
353
// GetUserPolicy gets a user policy in IAM.
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,
362
resp := new(GetUserPolicyResp)
363
if err := iam.query(params, resp); err != nil {
370
// PutUserPolicy creates a user policy in IAM.
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,
380
resp := new(SimpleResp)
381
if err := iam.postQuery(params, resp); err != nil {
387
// DeleteUserPolicy deletes a user policy from IAM.
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,
396
resp := new(SimpleResp)
397
if err := iam.query(params, resp); err != nil {
403
type SimpleResp struct {
404
RequestId string `xml:"ResponseMetadata>RequestId"`
407
type xmlErrors struct {
408
Errors []Error `xml:"Error"`
411
// Error encapsulates an IAM error.
413
// HTTP status code of the error.
416
// AWS code of the error.
419
// Message explaining the error.
423
func (e *Error) Error() string {
426
prefix = e.Code + ": "
428
if prefix == "" && e.StatusCode > 0 {
429
prefix = strconv.Itoa(e.StatusCode) + ": "
431
return prefix + e.Message