-
Notifications
You must be signed in to change notification settings - Fork 0
/
subject.go
78 lines (65 loc) · 2.1 KB
/
subject.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package data
import (
"errors"
"fmt"
"regexp"
"strconv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
)
// Subject represents the subject to deny.
type Subject struct {
CreatedAtEpochMillis uint64
CIDR string
ProtocolNumber int64
FromPort int64
ToPort int64
}
var subjectPattern = regexp.MustCompile("^([0-9]+):([0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}/[0-9]{1,2}):([0-9]+)(?::([0-9]{1,5})-([0-9]{1,5}))?$")
var (
errInvalidSubjectFormat = errors.New("invalid subject string has come")
)
// ParseSubjectString parses string and make a new Subject.
func ParseSubjectString(subjectString string) (*Subject, error) {
subjectSubmatch := subjectPattern.FindStringSubmatch(subjectString)
if len(subjectSubmatch) < 6 {
return &Subject{}, fmt.Errorf("%w: %s (expected pattern: %s)", errInvalidSubjectFormat, subjectString, subjectPattern)
}
createdAtEpochMillis, _ := strconv.ParseUint(subjectSubmatch[1], 10, 64)
cidr := subjectSubmatch[2]
protocolNumber, _ := strconv.ParseInt(subjectSubmatch[3], 10, 64)
var fromPort int64
fromPortStr := subjectSubmatch[4]
if fromPortStr != "" {
fromPort, _ = strconv.ParseInt(fromPortStr, 10, 64)
}
var toPort int64
toPortStr := subjectSubmatch[5]
if toPortStr != "" {
toPort, _ = strconv.ParseInt(toPortStr, 10, 64)
}
return &Subject{
CreatedAtEpochMillis: createdAtEpochMillis,
CIDR: cidr,
ProtocolNumber: protocolNumber,
FromPort: fromPort,
ToPort: toPort,
}, nil
}
// String converts a struct to string.
func (s *Subject) String() string {
if s.FromPort == 0 || s.ToPort == 0 {
return fmt.Sprintf("%d:%s:%d", s.CreatedAtEpochMillis, s.CIDR, s.ProtocolNumber)
}
return fmt.Sprintf("%d:%s:%d:%d-%d", s.CreatedAtEpochMillis, s.CIDR, s.ProtocolNumber, s.FromPort, s.ToPort)
}
// PortRange returns EC2 port-range according to the struct.
func (s *Subject) PortRange() *ec2.PortRange {
if s.FromPort != 0 && s.ToPort != 0 {
return &ec2.PortRange{
From: aws.Int64(s.FromPort),
To: aws.Int64(s.ToPort),
}
}
return nil
}