packer-cn/builder/osc/common/step_security_group.go

200 lines
5.6 KiB
Go

package common
import (
"context"
"fmt"
"log"
"strings"
"github.com/antihax/optional"
"github.com/hashicorp/packer-plugin-sdk/communicator"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/uuid"
"github.com/outscale/osc-sdk-go/osc"
)
type StepSecurityGroup struct {
CommConfig *communicator.Config
SecurityGroupFilter SecurityGroupFilterOptions
SecurityGroupIds []string
TemporarySGSourceCidr string
createdGroupId string
}
func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
var (
ui = state.Get("ui").(packersdk.Ui)
conn = state.Get("osc").(*osc.APIClient)
netID = state.Get("net_id").(string)
)
if len(s.SecurityGroupIds) > 0 {
resp, _, err := conn.SecurityGroupApi.ReadSecurityGroups(context.Background(), &osc.ReadSecurityGroupsOpts{
ReadSecurityGroupsRequest: optional.NewInterface(osc.ReadSecurityGroupsRequest{
Filters: osc.FiltersSecurityGroup{
SecurityGroupIds: s.SecurityGroupIds,
},
}),
})
if err != nil || len(resp.SecurityGroups) == 0 {
err := fmt.Errorf("Couldn't find specified security group: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
log.Printf("Using specified security groups: %v", s.SecurityGroupIds)
state.Put("securityGroupIds", s.SecurityGroupIds)
return multistep.ActionContinue
}
if !s.SecurityGroupFilter.Empty() {
filterReq := buildSecurityGroupFilters(s.SecurityGroupFilter.Filters)
log.Printf("Using SecurityGroup Filters %v", filterReq)
resp, _, err := conn.SecurityGroupApi.ReadSecurityGroups(context.Background(), &osc.ReadSecurityGroupsOpts{
ReadSecurityGroupsRequest: optional.NewInterface(osc.ReadSecurityGroupsRequest{
Filters: filterReq,
}),
})
if err != nil || len(resp.SecurityGroups) == 0 {
err := fmt.Errorf("Couldn't find security groups for filter: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
securityGroupIds := []string{}
for _, sg := range resp.SecurityGroups {
securityGroupIds = append(securityGroupIds, sg.SecurityGroupId)
}
ui.Message(fmt.Sprintf("Found Security Group(s): %s", strings.Join(securityGroupIds, ", ")))
state.Put("securityGroupIds", securityGroupIds)
return multistep.ActionContinue
}
/* Create the group */
groupName := fmt.Sprintf("packer_osc_%s", uuid.TimeOrderedUUID())
ui.Say(fmt.Sprintf("Creating temporary security group for this instance: %s", groupName))
createSGReq := osc.CreateSecurityGroupRequest{
SecurityGroupName: groupName,
NetId: netID,
Description: "Temporary group for Packer",
}
resp, _, err := conn.SecurityGroupApi.CreateSecurityGroup(context.Background(), &osc.CreateSecurityGroupOpts{
CreateSecurityGroupRequest: optional.NewInterface(createSGReq),
})
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
// Set the group ID so we can delete it later
s.createdGroupId = resp.SecurityGroup.SecurityGroupId
port := s.CommConfig.Port()
if port == 0 {
if s.CommConfig.Type != "none" {
state.Put("error", "port must be set to a non-zero value.")
return multistep.ActionHalt
}
}
// Authorize the SSH access for the security group
createSGRReq := osc.CreateSecurityGroupRuleRequest{
SecurityGroupId: resp.SecurityGroup.SecurityGroupId,
Flow: "Inbound",
Rules: []osc.SecurityGroupRule{
{
FromPortRange: int32(port),
ToPortRange: int32(port),
IpRanges: []string{s.TemporarySGSourceCidr},
IpProtocol: "tcp",
},
},
}
ui.Say(fmt.Sprintf("Authorizing access to port %d from %s in the temporary security group...", port, s.TemporarySGSourceCidr))
_, _, err = conn.SecurityGroupRuleApi.CreateSecurityGroupRule(context.Background(), &osc.CreateSecurityGroupRuleOpts{
CreateSecurityGroupRuleRequest: optional.NewInterface(createSGRReq),
})
if err != nil {
err := fmt.Errorf("Error authorizing temporary security group: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Set some state data for use in future steps
state.Put("securityGroupIds", []string{s.createdGroupId})
return multistep.ActionContinue
}
func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
if s.createdGroupId == "" {
return
}
var (
ui = state.Get("ui").(packersdk.Ui)
conn = state.Get("osc").(*osc.APIClient)
)
ui.Say("Deleting temporary security group...")
_, _, err := conn.SecurityGroupApi.DeleteSecurityGroup(context.Background(), &osc.DeleteSecurityGroupOpts{
DeleteSecurityGroupRequest: optional.NewInterface(osc.DeleteSecurityGroupRequest{
SecurityGroupId: s.createdGroupId,
}),
})
if err != nil {
ui.Error(fmt.Sprintf(
"Error cleaning up security group. Please delete the group manually: %s", s.createdGroupId))
}
}
func buildSecurityGroupFilters(input map[string]string) osc.FiltersSecurityGroup {
var filters osc.FiltersSecurityGroup
for k, v := range input {
filterValue := []string{v}
switch name := k; name {
case "account_ids":
filters.AccountIds = filterValue
case "security_group_ids":
filters.SecurityGroupIds = filterValue
case "security_group_names":
filters.SecurityGroupNames = filterValue
case "tag_keys":
filters.TagKeys = filterValue
case "tag_values":
filters.TagValues = filterValue
case "tags":
filters.Tags = filterValue
default:
log.Printf("[Debug] Unknown Filter Name: %s.", name)
}
}
return filters
}