1package egoscale 2 3import ( 4 "context" 5 "fmt" 6 "net/url" 7 "strconv" 8 "strings" 9) 10 11// SecurityGroup represent a firewalling set of rules 12type SecurityGroup struct { 13 Account string `json:"account,omitempty" doc:"the account owning the security group"` 14 Description string `json:"description,omitempty" doc:"the description of the security group"` 15 EgressRule []EgressRule `json:"egressrule,omitempty" doc:"the list of egress rules associated with the security group"` 16 ID *UUID `json:"id" doc:"the ID of the security group"` 17 IngressRule []IngressRule `json:"ingressrule,omitempty" doc:"the list of ingress rules associated with the security group"` 18 Name string `json:"name,omitempty" doc:"the name of the security group"` 19} 20 21// UserSecurityGroup converts a SecurityGroup to a UserSecurityGroup 22func (sg SecurityGroup) UserSecurityGroup() UserSecurityGroup { 23 return UserSecurityGroup{ 24 Group: sg.Name, 25 } 26} 27 28// ListRequest builds the ListSecurityGroups request 29func (sg SecurityGroup) ListRequest() (ListCommand, error) { 30 req := &ListSecurityGroups{ 31 ID: sg.ID, 32 SecurityGroupName: sg.Name, 33 } 34 35 return req, nil 36} 37 38// Delete deletes the given Security Group 39func (sg SecurityGroup) Delete(ctx context.Context, client *Client) error { 40 if sg.ID == nil && sg.Name == "" { 41 return fmt.Errorf("a SecurityGroup may only be deleted using ID or Name") 42 } 43 44 req := &DeleteSecurityGroup{} 45 46 if sg.ID != nil { 47 req.ID = sg.ID 48 } else { 49 req.Name = sg.Name 50 } 51 52 return client.BooleanRequestWithContext(ctx, req) 53} 54 55// RuleByID returns IngressRule or EgressRule by a rule ID 56func (sg SecurityGroup) RuleByID(ruleID UUID) (*IngressRule, *EgressRule) { 57 for i, in := range sg.IngressRule { 58 if in.RuleID.Equal(ruleID) { 59 return &sg.IngressRule[i], nil 60 } 61 } 62 63 for i, out := range sg.EgressRule { 64 if out.RuleID.Equal(ruleID) { 65 return nil, &sg.EgressRule[i] 66 } 67 } 68 69 return nil, nil 70} 71 72// IngressRule represents the ingress rule 73type IngressRule struct { 74 CIDR *CIDR `json:"cidr,omitempty" doc:"the CIDR notation for the base IP address of the security group rule"` 75 Description string `json:"description,omitempty" doc:"description of the security group rule"` 76 EndPort uint16 `json:"endport,omitempty" doc:"the ending port of the security group rule "` 77 IcmpCode int `json:"icmpcode,omitempty" doc:"the code for the ICMP message response"` 78 IcmpType int `json:"icmptype,omitempty" doc:"the type of the ICMP message response"` 79 Protocol string `json:"protocol,omitempty" doc:"the protocol of the security group rule"` 80 RuleID *UUID `json:"ruleid" doc:"the id of the security group rule"` 81 SecurityGroupName string `json:"securitygroupname,omitempty" doc:"security group name"` 82 StartPort uint16 `json:"startport,omitempty" doc:"the starting port of the security group rule"` 83} 84 85// EgressRule represents the ingress rule 86type EgressRule IngressRule 87 88// UserSecurityGroup represents the traffic of another security group 89type UserSecurityGroup struct { 90 Group string `json:"group,omitempty"` 91} 92 93// String gives the UserSecurityGroup name 94func (usg UserSecurityGroup) String() string { 95 return usg.Group 96} 97 98// CreateSecurityGroup represents a security group creation 99type CreateSecurityGroup struct { 100 Name string `json:"name" doc:"name of the security group"` 101 Description string `json:"description,omitempty" doc:"the description of the security group"` 102 _ bool `name:"createSecurityGroup" description:"Creates a security group"` 103} 104 105// Response returns the struct to unmarshal 106func (CreateSecurityGroup) Response() interface{} { 107 return new(SecurityGroup) 108} 109 110// DeleteSecurityGroup represents a security group deletion 111type DeleteSecurityGroup struct { 112 ID *UUID `json:"id,omitempty" doc:"The ID of the security group. Mutually exclusive with name parameter"` 113 Name string `json:"name,omitempty" doc:"The ID of the security group. Mutually exclusive with id parameter"` 114 _ bool `name:"deleteSecurityGroup" description:"Deletes security group"` 115} 116 117// Response returns the struct to unmarshal 118func (DeleteSecurityGroup) Response() interface{} { 119 return new(BooleanResponse) 120} 121 122// AuthorizeSecurityGroupIngress (Async) represents the ingress rule creation 123type AuthorizeSecurityGroupIngress struct { 124 CIDRList []CIDR `json:"cidrlist,omitempty" doc:"the cidr list associated"` 125 Description string `json:"description,omitempty" doc:"the description of the ingress/egress rule"` 126 EndPort uint16 `json:"endport,omitempty" doc:"end port for this ingress/egress rule"` 127 IcmpCode int `json:"icmpcode,omitempty" doc:"error code for this icmp message"` 128 IcmpType int `json:"icmptype,omitempty" doc:"type of the icmp message being sent"` 129 Protocol string `json:"protocol,omitempty" doc:"TCP is default. UDP, ICMP, ICMPv6, AH, ESP, GRE, IPIP are the other supported protocols"` 130 SecurityGroupID *UUID `json:"securitygroupid,omitempty" doc:"The ID of the security group. Mutually exclusive with securitygroupname parameter"` 131 SecurityGroupName string `json:"securitygroupname,omitempty" doc:"The name of the security group. Mutually exclusive with securitygroupid parameter"` 132 StartPort uint16 `json:"startport,omitempty" doc:"start port for this ingress/egress rule"` 133 UserSecurityGroupList []UserSecurityGroup `json:"usersecuritygrouplist,omitempty" doc:"user to security group mapping"` 134 _ bool `name:"authorizeSecurityGroupIngress" description:"Authorize a particular ingress/egress rule for this security group"` 135} 136 137// Response returns the struct to unmarshal 138func (AuthorizeSecurityGroupIngress) Response() interface{} { 139 return new(AsyncJobResult) 140} 141 142// AsyncResponse returns the struct to unmarshal the async job 143func (AuthorizeSecurityGroupIngress) AsyncResponse() interface{} { 144 return new(SecurityGroup) 145} 146 147func (req AuthorizeSecurityGroupIngress) onBeforeSend(params url.Values) error { 148 // ICMP code and type may be zero but can also be omitted... 149 if strings.HasPrefix(strings.ToLower(req.Protocol), "icmp") { 150 params.Set("icmpcode", strconv.FormatInt(int64(req.IcmpCode), 10)) 151 params.Set("icmptype", strconv.FormatInt(int64(req.IcmpType), 10)) 152 } 153 // StartPort may be zero but can also be omitted... 154 if req.EndPort != 0 && req.StartPort == 0 { 155 params.Set("startport", "0") 156 } 157 return nil 158} 159 160// AuthorizeSecurityGroupEgress (Async) represents the egress rule creation 161type AuthorizeSecurityGroupEgress AuthorizeSecurityGroupIngress 162 163// Response returns the struct to unmarshal 164func (AuthorizeSecurityGroupEgress) Response() interface{} { 165 return new(AsyncJobResult) 166} 167 168// AsyncResponse returns the struct to unmarshal the async job 169func (AuthorizeSecurityGroupEgress) AsyncResponse() interface{} { 170 return new(SecurityGroup) 171} 172 173func (req AuthorizeSecurityGroupEgress) onBeforeSend(params url.Values) error { 174 return (AuthorizeSecurityGroupIngress)(req).onBeforeSend(params) 175} 176 177// RevokeSecurityGroupIngress (Async) represents the ingress/egress rule deletion 178type RevokeSecurityGroupIngress struct { 179 ID *UUID `json:"id" doc:"The ID of the ingress rule"` 180 _ bool `name:"revokeSecurityGroupIngress" description:"Deletes a particular ingress rule from this security group"` 181} 182 183// Response returns the struct to unmarshal 184func (RevokeSecurityGroupIngress) Response() interface{} { 185 return new(AsyncJobResult) 186} 187 188// AsyncResponse returns the struct to unmarshal the async job 189func (RevokeSecurityGroupIngress) AsyncResponse() interface{} { 190 return new(BooleanResponse) 191} 192 193// RevokeSecurityGroupEgress (Async) represents the ingress/egress rule deletion 194type RevokeSecurityGroupEgress struct { 195 ID *UUID `json:"id" doc:"The ID of the egress rule"` 196 _ bool `name:"revokeSecurityGroupEgress" description:"Deletes a particular egress rule from this security group"` 197} 198 199// Response returns the struct to unmarshal 200func (RevokeSecurityGroupEgress) Response() interface{} { 201 return new(AsyncJobResult) 202} 203 204// AsyncResponse returns the struct to unmarshal the async job 205func (RevokeSecurityGroupEgress) AsyncResponse() interface{} { 206 return new(BooleanResponse) 207} 208 209//go:generate go run generate/main.go -interface=Listable ListSecurityGroups 210 211// ListSecurityGroups represents a search for security groups 212type ListSecurityGroups struct { 213 ID *UUID `json:"id,omitempty" doc:"list the security group by the id provided"` 214 Keyword string `json:"keyword,omitempty" doc:"List by keyword"` 215 Page int `json:"page,omitempty"` 216 PageSize int `json:"pagesize,omitempty"` 217 SecurityGroupName string `json:"securitygroupname,omitempty" doc:"lists security groups by name"` 218 VirtualMachineID *UUID `json:"virtualmachineid,omitempty" doc:"lists security groups by virtual machine id"` 219 _ bool `name:"listSecurityGroups" description:"Lists security groups"` 220} 221 222// ListSecurityGroupsResponse represents a list of security groups 223type ListSecurityGroupsResponse struct { 224 Count int `json:"count"` 225 SecurityGroup []SecurityGroup `json:"securitygroup"` 226} 227