-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
421 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
sudo: required | ||
language: go | ||
go: | ||
- 1.9 | ||
# - 1.10 | ||
- 1.11 | ||
- 1.12 | ||
- tip | ||
matrix: | ||
allow_failures: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package iam | ||
|
||
import ( | ||
SDK "github.com/aws/aws-sdk-go/service/iam" | ||
|
||
"github.com/evalphobia/aws-sdk-go-wrapper/config" | ||
"github.com/evalphobia/aws-sdk-go-wrapper/log" | ||
"github.com/evalphobia/aws-sdk-go-wrapper/private/pointers" | ||
) | ||
|
||
const ( | ||
serviceName = "IAM" | ||
) | ||
|
||
// IAM has IAM client. | ||
type IAM struct { | ||
client *SDK.IAM | ||
|
||
logger log.Logger | ||
} | ||
|
||
// New returns initialized *IAM. | ||
func New(conf config.Config) (*IAM, error) { | ||
sess, err := conf.Session() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
svc := &IAM{ | ||
client: SDK.New(sess), | ||
logger: log.DefaultLogger, | ||
} | ||
return svc, nil | ||
} | ||
|
||
// SetLogger sets logger. | ||
func (svc *IAM) SetLogger(logger log.Logger) { | ||
svc.logger = logger | ||
} | ||
|
||
// GetGroup executes GetGroup operation. | ||
func (svc *IAM) GetGroup(groupName string) (*SDK.GetGroupOutput, error) { | ||
output, err := svc.client.GetGroup(&SDK.GetGroupInput{ | ||
GroupName: pointers.String(groupName), | ||
}) | ||
if err != nil { | ||
svc.Errorf("error on `GetGroup` operation; error=[%s]; groupName=[%s];", err.Error(), groupName) | ||
return nil, err | ||
} | ||
return output, nil | ||
} | ||
|
||
// GetPolicyVersion executes GetPolicyVersion operation. | ||
func (svc *IAM) GetPolicyVersion(arn, versionID string) (*SDK.PolicyVersion, error) { | ||
output, err := svc.client.GetPolicyVersion(&SDK.GetPolicyVersionInput{ | ||
PolicyArn: pointers.String(arn), | ||
VersionId: pointers.String(versionID), | ||
}) | ||
if err != nil { | ||
svc.Errorf("error on `GetPolicyVersion` operation; error=[%s]; arn=[%s];", err.Error()) | ||
return nil, err | ||
} | ||
return output.PolicyVersion, nil | ||
} | ||
|
||
// ListAllPolicies fetches all of the policies list. | ||
func (svc *IAM) ListAllPolicies() ([]Policy, error) { | ||
return svc.listPolicies(&SDK.ListPoliciesInput{}) | ||
} | ||
|
||
// ListAttachedPolicies fetches attached policy list. | ||
func (svc *IAM) ListAttachedPolicies() ([]Policy, error) { | ||
return svc.listPolicies(&SDK.ListPoliciesInput{ | ||
OnlyAttached: pointers.Bool(true), | ||
}) | ||
} | ||
|
||
// listPolicies executes ListPolicies operation. | ||
func (svc *IAM) listPolicies(input *SDK.ListPoliciesInput) ([]Policy, error) { | ||
// set default limit | ||
if input.MaxItems == nil { | ||
input.MaxItems = pointers.Long64(1000) | ||
} | ||
|
||
output, err := svc.client.ListPolicies(input) | ||
if err != nil { | ||
svc.Errorf("error on `ListPolicies` operation; error=%s;", err.Error()) | ||
return nil, err | ||
} | ||
return NewPolicies(output.Policies), nil | ||
} | ||
|
||
// ListEntitiesForPolicy executes ListEntitiesForPolicy operation. | ||
func (svc *IAM) ListEntitiesForPolicy(arn string) ([]PolicyEntity, error) { | ||
output, err := svc.client.ListEntitiesForPolicy(&SDK.ListEntitiesForPolicyInput{ | ||
PolicyArn: pointers.String(arn), | ||
}) | ||
if err != nil { | ||
svc.Errorf("error on `ListEntitiesForPolicy` operation; error=%s;", err.Error()) | ||
return nil, err | ||
} | ||
return NewPolicyEntityList(output), nil | ||
} | ||
|
||
// Infof logging information. | ||
func (svc *IAM) Infof(format string, v ...interface{}) { | ||
svc.logger.Infof(serviceName, format, v...) | ||
} | ||
|
||
// Errorf logging error information. | ||
func (svc *IAM) Errorf(format string, v ...interface{}) { | ||
svc.logger.Errorf(serviceName, format, v...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package iam | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/evalphobia/aws-sdk-go-wrapper/config" | ||
) | ||
|
||
func getTestConfig() config.Config { | ||
return config.Config{ | ||
AccessKey: "access", | ||
SecretKey: "secret", | ||
} | ||
} | ||
|
||
func TestNew(t *testing.T) { | ||
a := assert.New(t) | ||
|
||
svc, err := New(getTestConfig()) | ||
a.NoError(err) | ||
a.NotNil(svc.client) | ||
a.Equal("iam", svc.client.ServiceName) | ||
a.Equal("https://iam.amazonaws.com", svc.client.Endpoint) | ||
|
||
region := "us-west-2" | ||
svc, err = New(config.Config{ | ||
Region: region, | ||
}) | ||
a.NoError(err) | ||
a.Equal("https://iam.amazonaws.com", svc.client.Endpoint, "IAM endpoint is global") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package iam | ||
|
||
import ( | ||
"time" | ||
|
||
SDK "github.com/aws/aws-sdk-go/service/iam" | ||
) | ||
|
||
// Policy contains IAM policy data. | ||
type Policy struct { | ||
ARN string | ||
PolicyID string | ||
PolicyName string | ||
VersionID string | ||
Description string | ||
AttachmentCount int64 | ||
CreateDate time.Time | ||
UpdateDate time.Time | ||
} | ||
|
||
// NewPoilicy returns initialized Policy from *SDK.Policy. | ||
func NewPoilicy(p *SDK.Policy) Policy { | ||
pp := Policy{} | ||
if p.Arn != nil { | ||
pp.ARN = *p.Arn | ||
} | ||
if p.PolicyId != nil { | ||
pp.PolicyID = *p.PolicyId | ||
} | ||
if p.PolicyName != nil { | ||
pp.PolicyName = *p.PolicyName | ||
} | ||
if p.DefaultVersionId != nil { | ||
pp.VersionID = *p.DefaultVersionId | ||
} | ||
if p.Description != nil { | ||
pp.Description = *p.Description | ||
} | ||
if p.AttachmentCount != nil { | ||
pp.AttachmentCount = *p.AttachmentCount | ||
} | ||
if p.CreateDate != nil { | ||
pp.CreateDate = *p.CreateDate | ||
} | ||
if p.UpdateDate != nil { | ||
pp.UpdateDate = *p.UpdateDate | ||
} | ||
return pp | ||
} | ||
|
||
// NewPolicies converts from []*SDK.Policy to []Policy. | ||
func NewPolicies(list []*SDK.Policy) []Policy { | ||
result := make([]Policy, len(list)) | ||
for i, p := range list { | ||
result[i] = NewPoilicy(p) | ||
} | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package iam | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/url" | ||
) | ||
|
||
const ( | ||
effectAllow = "Allow" | ||
effectDeny = "Deny" | ||
) | ||
|
||
// PolicyDocument contains permission data of a policy. | ||
type PolicyDocument struct { | ||
Version string `json:"Version"` | ||
Statement []Statement `json:"Statement"` | ||
} | ||
|
||
// used for multiple statements. | ||
type documentForUnmarshal struct { | ||
Version string `json:"Version"` | ||
Statement []Statement `json:"Statement"` | ||
} | ||
|
||
// used for single statement. | ||
type documentForUnmarshalSingle struct { | ||
Version string `json:"Version"` | ||
Statement Statement `json:"Statement"` | ||
} | ||
|
||
// NewPolicyDocumentFromDocument returns initialized PolicyDocument from response data. | ||
func NewPolicyDocumentFromDocument(document string) (PolicyDocument, error) { | ||
s, err := url.QueryUnescape(document) | ||
if err != nil { | ||
return PolicyDocument{}, err | ||
} | ||
return NewPolicyDocumentFromJSONString(s) | ||
} | ||
|
||
// NewPolicyDocumentFromJSONString returns initialized PolicyDocument from JSON data. | ||
func NewPolicyDocumentFromJSONString(data string) (PolicyDocument, error) { | ||
p := PolicyDocument{} | ||
err := json.Unmarshal([]byte(data), &p) | ||
if err != nil { | ||
fmt.Printf("[%s]\n\n", string(data)) | ||
} | ||
return p, err | ||
} | ||
|
||
// UnmarshalJSON converts from json to *PolicyDocument. | ||
func (p *PolicyDocument) UnmarshalJSON(data []byte) error { | ||
d1 := documentForUnmarshal{} | ||
err := json.Unmarshal(data, &d1) | ||
if err == nil { | ||
p.Version = d1.Version | ||
p.Statement = d1.Statement | ||
return nil | ||
} | ||
|
||
d2 := documentForUnmarshalSingle{} | ||
err = json.Unmarshal(data, &d2) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
p.Version = d2.Version | ||
p.Statement = []Statement{d2.Statement} | ||
return nil | ||
} | ||
|
||
// Statement represents statement of iam policy. | ||
type Statement struct { | ||
Sid string `json:"Sid"` | ||
Effect string `json:"Effect"` | ||
Action []string `json:"Action"` | ||
Resource []string `json:"Resource"` | ||
} | ||
|
||
// IsAllow checks that effect is allow. | ||
func (s *Statement) IsAllow() bool { | ||
return s.Effect == effectAllow | ||
} | ||
|
||
// IsDeny checks that effect is deny. | ||
func (s *Statement) IsDeny() bool { | ||
return s.Effect == effectDeny | ||
} | ||
|
||
// UnmarshalJSON converts from json to *Statement. | ||
func (s *Statement) UnmarshalJSON(data []byte) error { | ||
var m map[string]interface{} | ||
json.Unmarshal(data, &m) | ||
return s.setFromMap(m) | ||
} | ||
|
||
// used for converting from json data to *Statement | ||
func (s *Statement) setFromMap(m map[string]interface{}) error { | ||
if v, ok := m["Sid"].(string); ok { | ||
s.Sid = v | ||
} | ||
if v, ok := m["Effect"].(string); ok { | ||
s.Effect = v | ||
} | ||
if v, ok := m["Action"]; ok { | ||
switch v := v.(type) { | ||
case []interface{}: | ||
s.Action = toStringList(v) | ||
case string: | ||
s.Action = []string{v} | ||
} | ||
} | ||
if v, ok := m["Resource"]; ok { | ||
switch v := v.(type) { | ||
case []interface{}: | ||
s.Resource = toStringList(v) | ||
case string: | ||
s.Resource = []string{v} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func toStringList(list []interface{}) []string { | ||
result := make([]string, 0, len(list)) | ||
for _, v := range list { | ||
if v, ok := v.(string); ok { | ||
result = append(result, v) | ||
} | ||
} | ||
return result | ||
} |
Oops, something went wrong.