github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/joyent/instance_firewall.go (about)

     1  // Copyright 2013 Joyent Inc.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package joyent
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/joyent/gosdc/cloudapi"
    11  
    12  	"github.com/juju/juju/environs/config"
    13  	"github.com/juju/juju/environs/context"
    14  	"github.com/juju/juju/network"
    15  )
    16  
    17  const (
    18  	firewallRuleVm = "FROM tag %s TO vm %s ALLOW %s %s"
    19  )
    20  
    21  // Helper method to create a firewall rule string for the given machine Id and port
    22  func createFirewallRuleVm(envName string, machineId string, portRange network.IngressRule) string {
    23  	ports := []string{}
    24  	for p := portRange.FromPort; p <= portRange.ToPort; p++ {
    25  		ports = append(ports, fmt.Sprintf("PORT %d", p))
    26  	}
    27  	var portList string
    28  	if len(ports) > 1 {
    29  		portList = fmt.Sprintf("( %s )", strings.Join(ports, " AND "))
    30  	} else if len(ports) == 1 {
    31  		portList = ports[0]
    32  	}
    33  	return fmt.Sprintf(firewallRuleVm, envName, machineId, strings.ToLower(portRange.Protocol), portList)
    34  }
    35  
    36  func (inst *joyentInstance) OpenPorts(ctx context.ProviderCallContext, machineId string, ports []network.IngressRule) error {
    37  	if inst.env.Config().FirewallMode() != config.FwInstance {
    38  		return fmt.Errorf("invalid firewall mode %q for opening ports on instance", inst.env.Config().FirewallMode())
    39  	}
    40  
    41  	fwRules, err := inst.env.compute.cloudapi.ListFirewallRules()
    42  	if err != nil {
    43  		return fmt.Errorf("cannot get firewall rules: %v", err)
    44  	}
    45  
    46  	machineId = string(inst.Id())
    47  	for _, p := range ports {
    48  		rule := createFirewallRuleVm(inst.env.Config().Name(), machineId, p)
    49  		if e, id := ruleExists(fwRules, rule); e {
    50  			_, err := inst.env.compute.cloudapi.EnableFirewallRule(id)
    51  			if err != nil {
    52  				return fmt.Errorf("couldn't enable rule %s: %v", rule, err)
    53  			}
    54  		} else {
    55  			_, err := inst.env.compute.cloudapi.CreateFirewallRule(cloudapi.CreateFwRuleOpts{
    56  				Enabled: true,
    57  				Rule:    rule,
    58  			})
    59  			if err != nil {
    60  				return fmt.Errorf("couldn't create rule %s: %v", rule, err)
    61  			}
    62  		}
    63  	}
    64  
    65  	logger.Infof("ports %v opened for instance %q", ports, machineId)
    66  
    67  	return nil
    68  }
    69  
    70  func (inst *joyentInstance) ClosePorts(ctx context.ProviderCallContext, machineId string, ports []network.IngressRule) error {
    71  	if inst.env.Config().FirewallMode() != config.FwInstance {
    72  		return fmt.Errorf("invalid firewall mode %q for closing ports on instance", inst.env.Config().FirewallMode())
    73  	}
    74  
    75  	fwRules, err := inst.env.compute.cloudapi.ListFirewallRules()
    76  	if err != nil {
    77  		return fmt.Errorf("cannot get firewall rules: %v", err)
    78  	}
    79  
    80  	machineId = string(inst.Id())
    81  	for _, p := range ports {
    82  		rule := createFirewallRuleVm(inst.env.Config().Name(), machineId, p)
    83  		if e, id := ruleExists(fwRules, rule); e {
    84  			_, err := inst.env.compute.cloudapi.DisableFirewallRule(id)
    85  			if err != nil {
    86  				return fmt.Errorf("couldn't disable rule %s: %v", rule, err)
    87  			}
    88  		} else {
    89  			_, err := inst.env.compute.cloudapi.CreateFirewallRule(cloudapi.CreateFwRuleOpts{
    90  				Enabled: false,
    91  				Rule:    rule,
    92  			})
    93  			if err != nil {
    94  				return fmt.Errorf("couldn't create rule %s: %v", rule, err)
    95  			}
    96  		}
    97  	}
    98  
    99  	logger.Infof("ports %v closed for instance %q", ports, machineId)
   100  
   101  	return nil
   102  }
   103  
   104  func (inst *joyentInstance) IngressRules(ctx context.ProviderCallContext, machineId string) ([]network.IngressRule, error) {
   105  	if inst.env.Config().FirewallMode() != config.FwInstance {
   106  		return nil, fmt.Errorf("invalid firewall mode %q for retrieving ingress rules from instance", inst.env.Config().FirewallMode())
   107  	}
   108  
   109  	machineId = string(inst.Id())
   110  	fwRules, err := inst.env.compute.cloudapi.ListMachineFirewallRules(machineId)
   111  	if err != nil {
   112  		return nil, fmt.Errorf("cannot get firewall rules: %v", err)
   113  	}
   114  
   115  	return getRules(inst.env.Config().Name(), fwRules)
   116  }