1package awsspec
2
3import (
4	"reflect"
5	"strings"
6	"testing"
7)
8
9func TestBuildPolicyConditions(t *testing.T) {
10	tcases := []struct {
11		input  string
12		output *policyCondition
13	}{
14		{"aws:UserAgent==Example Corp Java Client", &policyCondition{Type: "StringEquals", Key: "aws:UserAgent", Value: "Example Corp Java Client"}},
15		{"aws:UserAgent!=Example Corp Java Client", &policyCondition{Type: "StringNotEquals", Key: "aws:UserAgent", Value: "Example Corp Java Client"}},
16		{"s3:prefix=~'home/'", &policyCondition{Type: "StringLike", Key: "s3:prefix", Value: "home/"}},
17		{"s3:prefix!~\"\"", &policyCondition{Type: "StringNotLike", Key: "s3:prefix", Value: ""}},
18		{"s3:prefix!~", &policyCondition{Type: "StringNotLike", Key: "s3:prefix", Value: ""}},
19		{"s3:max-keys==10", &policyCondition{Type: "NumericEquals", Key: "s3:max-keys", Value: "10"}},
20		{"s3:max-keys!=10", &policyCondition{Type: "NumericNotEquals", Key: "s3:max-keys", Value: "10"}},
21		{"s3:max-keys<10", &policyCondition{Type: "NumericLessThan", Key: "s3:max-keys", Value: "10"}},
22		{"s3:max-keys<=10", &policyCondition{Type: "NumericLessThanEquals", Key: "s3:max-keys", Value: "10"}},
23		{"s3:max-keys>10", &policyCondition{Type: "NumericGreaterThan", Key: "s3:max-keys", Value: "10"}},
24		{"s3:max-keys>=10", &policyCondition{Type: "NumericGreaterThanEquals", Key: "s3:max-keys", Value: "10"}},
25		{"aws:CurrentTime==2013-06-30T00:00:00Z", &policyCondition{Type: "DateEquals", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
26		{"aws:CurrentTime!=2013-06-30T00:00:00Z", &policyCondition{Type: "DateNotEquals", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
27		{"aws:CurrentTime<2013-06-30T00:00:00Z", &policyCondition{Type: "DateLessThan", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
28		{"aws:CurrentTime<=2013-06-30T00:00:00Z", &policyCondition{Type: "DateLessThanEquals", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
29		{"aws:CurrentTime>2013-06-30T00:00:00Z", &policyCondition{Type: "DateGreaterThan", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
30		{"aws:CurrentTime>=2013-06-30T00:00:00Z", &policyCondition{Type: "DateGreaterThanEquals", Key: "aws:CurrentTime", Value: "2013-06-30T00:00:00Z"}},
31		{"aws:SecureTransport==true", &policyCondition{Type: "Bool", Key: "aws:SecureTransport", Value: "true"}},
32		{"aws:SecureTransport!=true", &policyCondition{Type: "Bool", Key: "aws:SecureTransport", Value: "false"}},
33		{"aws:binarykey==QmluYXJ5VmFsdWVJbkJhc2U2NA==", &policyCondition{Type: "BinaryEquals", Key: "aws:binarykey", Value: "QmluYXJ5VmFsdWVJbkJhc2U2NA=="}},
34		{"aws:SourceIp==203.0.113.0/24", &policyCondition{Type: "IpAddress", Key: "aws:SourceIp", Value: "203.0.113.0/24"}},
35		{"aws:SourceIp!=203.0.113.0", &policyCondition{Type: "NotIpAddress", Key: "aws:SourceIp", Value: "203.0.113.0"}},
36		{"aws:SourceIp==2001:DB8:1234:5678::/64", &policyCondition{Type: "IpAddress", Key: "aws:SourceIp", Value: "2001:DB8:1234:5678::/64"}},
37		{"aws:SourceArn==arn:aws:sns:REGION:123456789012:TOPIC-ID", &policyCondition{Type: "ArnEquals", Key: "aws:SourceArn", Value: "arn:aws:sns:REGION:123456789012:TOPIC-ID"}},
38		{"aws:SourceArn!=arn:aws:sns:*:*:TOPIC-ID", &policyCondition{Type: "ArnNotEquals", Key: "aws:SourceArn", Value: "arn:aws:sns:*:*:TOPIC-ID"}},
39		{"aws:SourceArn=~arn:aws:sns:*:*:TOPIC-ID", &policyCondition{Type: "ArnLike", Key: "aws:SourceArn", Value: "arn:aws:sns:*:*:TOPIC-ID"}},
40		{"aws:SourceArn!~arn:aws:sns:*:*:TOPIC-ID", &policyCondition{Type: "ArnNotLike", Key: "aws:SourceArn", Value: "arn:aws:sns:*:*:TOPIC-ID"}},
41		{"aws:TokenIssueTime==Null", &policyCondition{Type: "Null", Key: "aws:TokenIssueTime", Value: "true"}},
42		{"aws:TokenIssueTime!=Null", &policyCondition{Type: "Null", Key: "aws:TokenIssueTime", Value: "false"}},
43	}
44	for i, tcase := range tcases {
45		cond, err := parseCondition(tcase.input)
46		if err != nil {
47			t.Fatalf("%d: %s", i+1, err)
48		}
49		if got, want := cond, tcase.output; !reflect.DeepEqual(got, want) {
50			t.Fatalf("%d: got %#v, want %#v", i+1, got, want)
51		}
52	}
53}
54
55func TestResolvePolicy(t *testing.T) {
56	p, err := lookupAWSPolicy("ec2", "readonly")
57	if err != nil {
58		t.Fatal(err)
59	}
60	if got, want := p.Name, "AmazonEC2ReadOnlyAccess"; got != want {
61		t.Fatalf("got %s, want %s", got, want)
62	}
63
64	p, err = lookupAWSPolicy("lambda", "full")
65	if err != nil {
66		t.Fatal(err)
67	}
68	if got, want := p.Name, "AWSLambdaFullAccess"; got != want {
69		t.Fatalf("got %s, want %s", got, want)
70	}
71
72	if _, err = lookupAWSPolicy("lambda", "fully"); err == nil {
73		t.Fatal("expecting error got none")
74	}
75	if _, err = lookupAWSPolicy("lava", "full"); err == nil {
76		t.Fatal("expecting error got none")
77	}
78}
79
80func TestResolvePolicyErrorMessageWithSuggestion(t *testing.T) {
81	_, err := lookupAWSPolicy("Administrator", "readonly")
82	if err == nil {
83		t.Fatal("expected error got none")
84	}
85
86	shouldContains := []string{
87		"arn:aws:iam::aws:policy/job-function/DatabaseAdministrator",
88		"arn:aws:iam::aws:policy/AdministratorAccess",
89	}
90
91	for _, e := range shouldContains {
92		if msg := err.Error(); !strings.Contains(msg, e) {
93			t.Errorf("expect '%s' to contain '%s'", msg, e)
94		}
95	}
96}
97