github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/provider/joyent/environ_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 "strconv" 9 "strings" 10 11 "github.com/joyent/gosdc/cloudapi" 12 13 "github.com/juju/juju/environs/config" 14 "github.com/juju/juju/network" 15 ) 16 17 const ( 18 firewallRuleAll = "FROM tag %s TO tag juju ALLOW %s PORT %d" 19 ) 20 21 // Helper method to create a firewall rule string for the given port 22 func createFirewallRuleAll(env *joyentEnviron, port network.Port) string { 23 return fmt.Sprintf(firewallRuleAll, env.Name(), strings.ToLower(port.Protocol), port.Number) 24 } 25 26 // Helper method to check if a firewall rule string already exist 27 func ruleExists(rules []cloudapi.FirewallRule, rule string) (bool, string) { 28 for _, r := range rules { 29 if strings.EqualFold(r.Rule, rule) { 30 return true, r.Id 31 } 32 } 33 34 return false, "" 35 } 36 37 // Helper method to get port from the given firewall rules 38 func getPorts(env *joyentEnviron, rules []cloudapi.FirewallRule) []network.Port { 39 ports := []network.Port{} 40 for _, r := range rules { 41 rule := r.Rule 42 if r.Enabled && strings.HasPrefix(rule, "FROM tag "+env.Name()) && strings.Contains(rule, "PORT") { 43 p := rule[strings.Index(rule, "ALLOW")+6 : strings.Index(rule, "PORT")-1] 44 n, _ := strconv.Atoi(rule[strings.LastIndex(rule, " ")+1:]) 45 port := network.Port{Protocol: p, Number: n} 46 ports = append(ports, port) 47 } 48 } 49 50 network.SortPorts(ports) 51 return ports 52 } 53 54 func (env *joyentEnviron) OpenPorts(ports []network.Port) error { 55 if env.Config().FirewallMode() != config.FwGlobal { 56 return fmt.Errorf("invalid firewall mode %q for opening ports on environment", env.Config().FirewallMode()) 57 } 58 59 fwRules, err := env.compute.cloudapi.ListFirewallRules() 60 if err != nil { 61 return fmt.Errorf("cannot get firewall rules: %v", err) 62 } 63 64 for _, p := range ports { 65 rule := createFirewallRuleAll(env, p) 66 if e, id := ruleExists(fwRules, rule); e { 67 _, err := env.compute.cloudapi.EnableFirewallRule(id) 68 if err != nil { 69 return fmt.Errorf("couldn't enable rule %s: %v", rule, err) 70 } 71 } else { 72 _, err := env.compute.cloudapi.CreateFirewallRule(cloudapi.CreateFwRuleOpts{ 73 Enabled: true, 74 Rule: rule, 75 }) 76 if err != nil { 77 return fmt.Errorf("couldn't create rule %s: %v", rule, err) 78 } 79 } 80 } 81 82 logger.Infof("ports %v opened in environment", ports) 83 84 return nil 85 } 86 87 func (env *joyentEnviron) ClosePorts(ports []network.Port) error { 88 if env.Config().FirewallMode() != config.FwGlobal { 89 return fmt.Errorf("invalid firewall mode %q for closing ports on environment", env.Config().FirewallMode()) 90 } 91 92 fwRules, err := env.compute.cloudapi.ListFirewallRules() 93 if err != nil { 94 return fmt.Errorf("cannot get firewall rules: %v", err) 95 } 96 97 for _, p := range ports { 98 rule := createFirewallRuleAll(env, p) 99 if e, id := ruleExists(fwRules, rule); e { 100 _, err := env.compute.cloudapi.DisableFirewallRule(id) 101 if err != nil { 102 return fmt.Errorf("couldn't disable rule %s: %v", rule, err) 103 } 104 } else { 105 _, err := env.compute.cloudapi.CreateFirewallRule(cloudapi.CreateFwRuleOpts{ 106 Enabled: false, 107 Rule: rule, 108 }) 109 if err != nil { 110 return fmt.Errorf("couldn't create rule %s: %v", rule, err) 111 } 112 } 113 } 114 115 logger.Infof("ports %v closed in environment", ports) 116 117 return nil 118 } 119 120 func (env *joyentEnviron) Ports() ([]network.Port, error) { 121 if env.Config().FirewallMode() != config.FwGlobal { 122 return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from environment", env.Config().FirewallMode()) 123 } 124 125 fwRules, err := env.compute.cloudapi.ListFirewallRules() 126 if err != nil { 127 return nil, fmt.Errorf("cannot get firewall rules: %v", err) 128 } 129 130 return getPorts(env, fwRules), nil 131 }