class Morpheus::Cli::SecurityGroups
Public Class Methods
load_security_group_file()
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1125 def self.load_security_group_file remote_file = security_group_file_path if File.exist? remote_file return YAML.load_file(remote_file) else {} end end
save_security_group(new_config)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1138 def self.save_security_group(new_config) fn = security_group_file_path if !Dir.exist?(File.dirname(fn)) FileUtils.mkdir_p(File.dirname(fn)) end File.open(fn, 'w') {|f| f.write new_config.to_yaml } #Store FileUtils.chmod(0600, fn) new_config end
security_group_file_path()
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1134 def self.security_group_file_path File.join(Morpheus::Cli.home_directory,"securitygroup") end
Public Instance Methods
add(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 209 def add(args) params = {} options = {:options => {}} cloud_id = nil resource_pool_id = nil tenants = nil group_access_all = nil group_access_list = nil group_defaults_list = nil optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[name] [options]") opts.on( '--name Name', String, "Name of the security group" ) do |val| options[:options]['name'] = val end opts.on( '--description Description', String, "Description of the security group" ) do |val| options[:options]['description'] = val end opts.on( '-c', '--cloud CLOUD', "Scoped Cloud Name or ID" ) do |val| cloud_id = val end opts.on( '--resource-pool ID', String, "ID of the Resource Pool for Amazon VPC and Azure Resource Group" ) do |val| resource_pool_id = val end opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val| group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '' end opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it group_access_list = [] else group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it group_defaults_list = [] else group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it options['tenants'] = [] else options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--can-manage LIST', Array, "Tenant Can Manage, comma separated list of account IDs that can manage") do |list| options['canManage'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end opts.on('--visibility [private|public]', String, "Visibility") do |val| options['visibility'] = val end opts.on('--active [on|off]', String, "Can be used to disable a security group") do |val| options[:options]['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '' end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) opts.footer = "Create a security group." + "\n" + "[name] is required. This is the name of the security group." end optparse.parse!(args) if args.count > 1 raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end if args[0] options[:options]['name'] = args[0] end connect(options) begin # load cloud cloud = nil if cloud_id cloud = find_cloud_by_name_or_id(cloud_id) return 1 if cloud.nil? options[:options]['zoneId'] = cloud['id'].to_s end # construct payload passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'securityGroup' => passed_options}) unless passed_options.empty? else # prompt for resource folder options payload = { 'securityGroup' => { } } # allow arbitrary -O options payload.deep_merge!({'securityGroup' => passed_options}) unless passed_options.empty? # Name options[:options]['name'] = options[:name] if options.key?(:name) v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options[:options]) payload['securityGroup']['name'] = v_prompt['name'] # Description v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options]) payload['securityGroup']['description'] = v_prompt['description'] # Scoped Cloud # /api/options/clouds requires groupId... begin scoped_clouds = [{"name" => "All", "value" => "all"}] clouds_response = @options_interface.options_for_source('cloudsForSecurityGroup',{}) if clouds_response['data'] clouds_response['data'].each do |it| scoped_clouds << {"name" => it['name'], "value" => it['value']} end end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Scoped Cloud', 'type' => 'select', 'selectOptions' => scoped_clouds, 'required' => false, 'defaultValue' => (payload['securityGroup']['zoneId'] || 'all')}], options[:options], @api_client) #v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Scoped Cloud', 'type' => 'select', 'optionSource' => 'cloudsForSecurityGroup', 'required' => false}], options[:options], @api_client) if !v_prompt['zoneId'].to_s.empty? && v_prompt['zoneId'].to_s != 'all' && v_prompt['zoneId'].to_s != '-1' payload['securityGroup']['zoneId'] = v_prompt['zoneId'] cloud = find_cloud_by_id(payload['securityGroup']['zoneId']) # parse --resource-pool # if resource_pool_id # resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id) # return 1 if resource_pool.nil? # end # prompt for zone specific settings that go under "securityGroup.customOptions" for some reason custom_options_values = prompt_security_group_custom_options(options, cloud, resource_pool_id) payload['securityGroup'].deep_merge!(custom_options_values) end rescue => ex # raise ex print yellow,"Failed to determine the available scoped clouds.",reset,"\n" end # Group Access if group_access_all != nil payload['resourcePermissions'] ||= {} payload['resourcePermissions']['all'] = group_access_all end if group_access_list != nil payload['resourcePermissions'] ||= {} payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id| site = {"id" => site_id.to_i} if group_defaults_list && group_defaults_list.include?(site_id) site["default"] = true end site end end # Tenants if options['tenants'] || options['canManage'] payload['tenantPermissions'] = {} payload['tenantPermissions']['accounts'] = ((options['tenants'] || []) + (options['canManage'] || [])).uniq payload['tenantPermissions']['canManageAccounts'] = options['canManage'] if options['canManage'] end # Visibility if options['visibility'] != nil payload['securityGroup']['visibility'] = options['visibility'] end # Active if options['active'] != nil payload['securityGroup']['active'] = options['active'] end end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.create(payload) return 0 end json_response = @security_groups_interface.create(payload) if options[:json] puts as_json(json_response, options) return 0 end print_green_success "Created security group #{json_response['securityGroup']['name']}" return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
add_location(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 572 def add_location(args) cloud_id = nil resource_pool_id = nil params = {} options = {:options => {}} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [options]") opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val| cloud_id = val end opts.on( '--resource-pool ID', String, "ID of the Resource Pool for Amazon VPC and Azure Resource Group" ) do |val| resource_pool_id = val end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) opts.footer = "Add security group to a location (cloud)." + "\n" + "[security-group] is required. This is the name or id of the security group." end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:1) connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? # construct payload passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'securityGroupLocation' => passed_options}) unless passed_options.empty? else # prompt for resource folder options payload = { 'securityGroupLocation' => { } } payload.deep_merge!({'securityGroupLocation' => passed_options}) unless passed_options.empty? cloud = nil if cloud_id options[:options]['zoneId'] = cloud_id end # Cloud prompt scoped_clouds = [] clouds_response = @options_interface.options_for_source('cloudsForSecurityGroup',{securityGroupId: security_group['id']}) if clouds_response['data'] clouds_response['data'].each do |it| scoped_clouds << {"name" => it['name'], "value" => it['value']} end end if scoped_clouds.empty? raise_command_error("Security group has 0 available clouds for adding a location", args, optparse) end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneId', 'fieldLabel' => 'Cloud', 'type' => 'select', 'selectOptions' => scoped_clouds, 'required' => true}], options[:options], @api_client) payload['securityGroupLocation']['zoneId'] = v_prompt['zoneId'] cloud = find_cloud_by_id(payload['securityGroupLocation']['zoneId']) return 1 if cloud.nil? # parse --resource-pool # if resource_pool_id # resource_pool = find_resource_pool_by_name_or_id(cloud['id'], resource_pool_id) # return 1 if resource_pool.nil? # end # prompt for zone specific settings that go under "securityGroup.customOptions" for some reason custom_options_values = prompt_security_group_custom_options(options, cloud, resource_pool_id) payload['securityGroupLocation'].deep_merge!(custom_options_values) end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.create_location(security_group['id'], payload) return 0 end json_response = @security_groups_interface.create_location(security_group['id'], payload) if options[:json] puts as_json(json_response, options) return 0 end print_green_success "Created security group location #{security_group['name']} - #{cloud['name']}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
add_rule(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 724 def add_rule(args) params = {} options = {:options => {}} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [options]") build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) opts.on( '--name VALUE', String, "Name of the rule" ) do |val| options[:options]['name'] = val end opts.on( '--direction VALUE', String, "Direction" ) do |val| options[:options]['direction'] = val end opts.on( '--rule-type VALUE', String, "Rule Type" ) do |val| options[:options]['ruleType'] = val end opts.on( '--protocol VALUE', String, "Protocol" ) do |val| options[:options]['protocol'] = val end opts.on( '--port-range VALUE', String, "Port Range" ) do |val| options[:options]['portRange'] = val end opts.on( '--source-type VALUE', String, "Source Type" ) do |val| options[:options]['sourceType'] = val end opts.on( '--source VALUE', String, "Source" ) do |val| options[:options]['source'] = val end opts.on( '--source-group VALUE', String, "Source Security Group" ) do |val| options[:options]['sourceGroup'] = val end opts.on( '--source-tier VALUE', String, "Source Tier" ) do |val| options[:options]['sourceTier'] = val end opts.on( '--destination-type VALUE', String, "Destination Type" ) do |val| options[:options]['destinationType'] = val end opts.on( '--destination VALUE', String, "Destination" ) do |val| options[:options]['destination'] = val end opts.on( '--destination-group VALUE', String, "Destination Security Group" ) do |val| options[:options]['destinationGroup'] = val end opts.on( '--destination-tier VALUE', String, "Destination Tier" ) do |val| options[:options]['destinationTier'] = val end opts.footer = "Create a security group rule." + "\n" + "[security-group] is required. This is the name or id of the security group." + "\n" "[name] is required. This is the name of the security group rule." end optparse.parse!(args) if args.count < 1 || args.count > 2 raise_command_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? # construct payload if args[1] options[:options]['name'] = args[1] end passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty? else # prompt for resource folder options payload = { 'rule' => { } } payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty? # prompt v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options[:options]) payload['rule']['name'] = v_prompt['name'] unless v_prompt['name'].nil? v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'direction', 'fieldLabel' => 'Direction', 'type' => 'select', 'optionSource' => 'securityGroupDirection', 'required' => true, 'defaultValue' => 'ingress'}], options[:options], @api_client) payload['rule']['direction'] = v_prompt['direction'] unless v_prompt['direction'].nil? rule_types = [{"name" => "Custom Rule", "value" => "customRule"}] instance_types = @options_interface.options_for_source('instanceTypes',{}) if instance_types['data'] instance_types['data'].each do |it| rule_types << {"name" => it['name'], "value" => it['code'] || it['value']} end end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'ruleType', 'fieldLabel' => 'Rule Type', 'type' => 'select', 'selectOptions' => rule_types, 'required' => true, 'defaultValue' => 'customRule'}], options[:options], @api_client) payload['rule']['ruleType'] = v_prompt['ruleType'] unless v_prompt['ruleType'].nil? if payload['rule']['ruleType'] == 'customRule' protocols = [{"name" => "TCP", "value" => "tcp"}, {"name" => "UDP", "value" => "udp"}, {"name" => "ICMP", "value" => "icmp"}] v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'protocol', 'fieldLabel' => 'Protocol', 'type' => 'select', 'selectOptions' => protocols, 'required' => true, 'defaultValue' => 'tcp'}], options[:options], @api_client) payload['rule']['protocol'] = v_prompt['protocol'] unless v_prompt['protocol'].nil? v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'portRange', 'fieldLabel' => 'Port Range', 'type' => 'text', 'required' => true}], options[:options]) payload['rule']['portRange'] = v_prompt['portRange'] unless v_prompt['portRange'].nil? end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceType', 'fieldLabel' => 'Source Type', 'type' => 'select', 'optionSource' => 'securityGroupSourceType', 'required' => true, 'defaultValue' => 'cidr'}], options[:options], @api_client, {'rule.securityGroupId': security_group['id'], 'securityGroupRule.direction': payload['rule']['direction']}) payload['rule']['sourceType'] = v_prompt['sourceType'] unless v_prompt['sourceType'].nil? if payload['rule']['sourceType'] == 'cidr' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'fieldLabel' => 'Source', 'type' => 'text', 'required' => true, 'description' => 'Source CIDR eg. 0.0.0.0/0'}], options[:options]) payload['rule']['source'] = v_prompt['source'] unless v_prompt['source'].nil? elsif payload['rule']['sourceType'] == 'group' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceGroup', 'fieldLabel' => 'Source Security Group', 'type' => 'select', 'optionSource' => 'securityGroups', 'required' => true}], options[:options], @api_client) payload['rule']['sourceGroup'] = {"id" => v_prompt['sourceGroup']} unless v_prompt['sourceGroup'].nil? elsif payload['rule']['sourceType'] == 'tier' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sourceTier', 'fieldLabel' => 'Source Tier', 'type' => 'select', 'optionSource' => 'tiers', 'required' => true}], options[:options], @api_client) payload['rule']['sourceTier'] = {"id" => v_prompt['sourceTier']} unless v_prompt['sourceTier'].nil? end v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationType', 'fieldLabel' => 'Destination Type', 'type' => 'select', 'optionSource' => 'securityGroupDestinationType', 'required' => true, 'defaultValue' => 'instance'}], options[:options], @api_client, {'rule.securityGroupId': security_group['id'], 'securityGroupRule.direction': payload['rule']['direction']}) payload['rule']['destinationType'] = v_prompt['destinationType'] unless v_prompt['destinationType'].nil? if payload['rule']['destinationType'] == 'cidr' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destination', 'fieldLabel' => 'Destination', 'type' => 'text', 'required' => true, 'description' => 'Destination CIDR eg. 0.0.0.0/0'}], options[:options]) payload['rule']['destination'] = v_prompt['destination'] unless v_prompt['destination'].nil? elsif payload['rule']['destinationType'] == 'group' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationGroup', 'fieldLabel' => 'Destination Security Group', 'type' => 'select', 'optionSource' => 'securityGroups', 'required' => true}], options[:options], @api_client) payload['rule']['destinationGroup'] = {"id" => v_prompt['destinationGroup']} unless v_prompt['destinationGroup'].nil? elsif payload['rule']['destinationType'] == 'tier' v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'destinationTier', 'fieldLabel' => 'Destination Tier', 'type' => 'select', 'optionSource' => 'tiers', 'required' => true}], options[:options], @api_client) payload['rule']['destinationTier'] = {"id" => v_prompt['destinationTier']} unless v_prompt['destinationTier'].nil? end end @security_group_rules_interface.setopts(options) if options[:dry_run] print_dry_run @security_group_rules_interface.dry.create(security_group['id'], payload) return 0 end json_response = @security_group_rules_interface.create(security_group['id'], payload) if options[:json] puts as_json(json_response, options) return 0 end display_name = (json_response['rule'] && json_response['rule']['name'].to_s != '') ? json_response['rule']['name'] : json_response['rule']['id'] print_green_success "Created security group rule #{display_name}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
connect(opts)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 12 def connect(opts) @api_client = establish_remote_appliance_connection(opts) @security_groups_interface = @api_client.security_groups @security_group_rules_interface = @api_client.security_group_rules @cloud_resource_pools_interface = @api_client.cloud_resource_pools @clouds_interface = @api_client.clouds @options_interface = @api_client.options @active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file @network_security_servers = @api_client.network_security_servers @network_servers = @api_client.network_servers end
get(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 76 def get(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote]) opts.footer = "Get details about a security group." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) exit_code, err = 0, nil security_group_id = nil if args[0].to_s =~ /\A\d{1,}\Z/ security_group_id = args[0].to_i else security_group = find_security_group_by_name(args[0]) return 1, "Security Group not found" if security_group.nil? security_group_id = security_group['id'] end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.get(security_group_id) return exit_code, err end json_response = @security_groups_interface.get(security_group_id) render_result = render_with_format(json_response, options, 'securityGroup') return exit_code, err if render_result security_group = json_response['securityGroup'] security_group_locations = json_response['locations'] || security_group['locations'] security_group_rules = json_response['rules'] || security_group['rules'] print_h1 "Security Group Details" print cyan description_cols = { "ID" => 'id', "Name" => 'name', "Description" => 'description', "Scoped Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : 'All' }, "Source" => lambda {|it| it['syncSource'] == 'external' ? 'SYNCED' : 'CREATED' }, "Visibility" => 'visibility', "Active" => lambda {|it| format_boolean(it['active']) }, "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.sort.join(', ') : '' }, } print_description_list(description_cols, security_group) # print reset,"\n" if security_group['resourcePermission'].nil? #print "\n", "No group access found", "\n" else print_h2 "Group Access" rows = [] if security_group['resourcePermission']['all'] rows.push({"name" => 'All'}) end if security_group['resourcePermission']['sites'] security_group['resourcePermission']['sites'].each do |site| rows.push(site) end end rows = rows.collect do |site| {group: site['name'], default: site['default'] ? 'Yes' : ''} end columns = [:group, :default] print cyan print as_pretty_table(rows, columns) end if security_group_locations && security_group_locations.size > 0 print_h2 "Locations" print cyan location_cols = { "ID" => 'id', "CLOUD" => lambda {|it| it['zone'] ? it['zone']['name'] : '' }, "EXTERNAL ID" => lambda {|it| it['externalId'] }, "RESOURCE POOL" => lambda {|it| it['zonePool'] ? it['zonePool']['name'] : '' } } puts as_pretty_table(security_group_locations, location_cols) else print reset,"\n" end if security_group_rules if security_group_rules == 0 #print cyan,"No rules.",reset,"\n" else print_h2 "Rules" print cyan # NAME DIRECTION SOURCE DESTINATION RULE TYPE PROTOCOL PORT RANGE rule_cols = { "ID" => 'id', "NAME" => 'name', "DIRECTION" => lambda {|it| it['direction'] }, "SOURCE" => lambda {|it| if it['sourceType'] == 'cidr' "Network: #{it['source']}" elsif it['sourceType'] == 'group' "Group: #{it['sourceGroup'] ? it['sourceGroup']['name'] : ''}" elsif it['sourceType'] == 'tier' "Tier: #{it['sourceTier'] ? it['sourceTier']['name'] : ''}" elsif it['sourceType'] == 'instance' "Instance" else it['sourceType'] end }, "DESTINATION" => lambda {|it| if it['destinationType'] == 'cidr' "Network: #{it['destination']}" elsif it['destinationType'] == 'group' "Group: #{it['destinationGroup'] ? it['destinationGroup']['name'] : ''}" elsif it['destinationType'] == 'tier' "Tier: #{it['destinationTier'] ? it['destinationTier']['name'] : ''}" elsif it['destinationType'] == 'instance' "Instance" else it['destinationType'] end }, "RULE TYPE" => lambda {|it| it['ruleType'] == 'customRule' ? 'Custom' : it['ruleType'] }, "PROTOCOL" => lambda {|it| it['protocol'] }, "PORT RANGE" => lambda {|it| it['portRange'] } } puts as_pretty_table(security_group_rules, rule_cols) end end return exit_code, err end
handle(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 24 def handle(args) handle_subcommand(args) end
list(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 29 def list(args) params = {} options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage() build_standard_list_options(opts, options) opts.footer = "List security groups." end optparse.parse!(args) # verify_args!(args:args, optparse:optparse, count:0) if args.count > 0 options[:phrase] = args.join(" ") end connect(options) params.merge!(parse_list_options(options)) @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.list(params) return end json_response = @security_groups_interface.list(params) render_response(json_response, options, "securityGroups") do security_groups = json_response['securityGroups'] title = "Morpheus Security Groups" subtitles = [] subtitles += parse_list_subtitles(options) print_h1 title, subtitles, options if security_groups.empty? print cyan,"No security groups found.",reset,"\n" else columns = { "ID" => 'id', "NAME" => 'name', #"DESCRIPTION" => 'description', "DESCRIPTION" => lambda {|it| truncate_string(it['description'], 30) }, #"USED BY" => lambda {|it| it['associations'] ? it['associations'] : '' }, "SCOPED CLOUD" => lambda {|it| it['zone'] ? it['zone']['name'] : 'All' }, "SOURCE" => lambda {|it| it['syncSource'] == 'external' ? 'SYNCED' : 'CREATED' } } print as_pretty_table(security_groups, columns, options) print_results_pagination(json_response) end print reset,"\n" end return 0, nil end
remove(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 532 def remove(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id]") build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote]) opts.footer = "Delete a security group." + "\n" + "[security-group] is required. This is the name or id of the security group." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group: #{security_group['name']}?") return 9, "aborted command" end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.delete(security_group['id']) return end json_response = @security_groups_interface.delete(security_group['id']) if options[:json] puts as_json(json_response, options) return 0 end #list([]) print_green_success "Removed security group #{args[0]}" return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
remove_location(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 659 def remove_location(args) cloud_id = nil resource_pool_id = nil params = {} options = {:options => {}} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [options]") opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val| cloud_id = val end build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote]) opts.footer = "Remove security group from a location (cloud)." + "\n" + "[security-group] is required. This is the name or id of the security group." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? # load cloud if cloud_id.nil? puts_error "#{Morpheus::Terminal.angry_prompt}missing required option: [cloud]\n#{optparse}" return 1 end cloud = find_cloud_by_name_or_id(cloud_id) return 1 if cloud.nil? security_group_location = nil if security_group['locations'] security_group_location = security_group['locations'].find {|it| it['zone']['id'] == cloud['id'] } end if security_group_location.nil? print_red_alert "Security group location not found for cloud #{cloud['name']}" return 1 end unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group location #{security_group['name']} - #{cloud['name']}?") return 9, "aborted command" end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.delete_location(security_group['id'], security_group_location['id']) return 0 end json_response = @security_groups_interface.delete_location(security_group['id'], security_group_location['id']) if options[:json] puts as_json(json_response, options) return 0 end print_green_success "Created security group location #{security_group['name']} - #{cloud['name']}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
remove_rule(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 877 def remove_rule(args) params = {} options = {:options => {}} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [id]") build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote]) opts.footer = "Delete a security group rule." + "\n" + "[security-group] is required. This is the name or id of the security group." + "\n" "[rule] is required. This is the name or id of the security group rule." end optparse.parse!(args) if args.count != 2 raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? #security_group_rule = find_security_group_rule_by_id(security_group['id'], args[1]) #return 1 if security_group_rule.nil? security_group_rule = nil if security_group['rules'] matching_rules = [] if args[1].to_s =~ /\A\d{1,}\Z/ matching_rules = security_group['rules'].select {|it| it['id'].to_s == args[1].to_s } else matching_rules = security_group['rules'].select {|it| it['name'] == args[1].to_s } end if matching_rules.size > 1 print_red_alert "#{matching_rules.size} security group rules found by name '#{args[1]}'" rows = matching_rules.collect do |it| {id: it['id'], name: it['name']} end puts as_pretty_table(rows, [:id, :name], {color:red}) return 1 else security_group_rule = matching_rules[0] end end if security_group_rule.nil? print_red_alert "Security group rule not found for '#{args[1]}'" return 1 end unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the security group rule: #{security_group_rule['id']}?") return 9, "aborted command" end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_group_rules_interface.dry.delete(security_group['id'], security_group_rule['id']) return 0 end json_response = @security_group_rules_interface.delete(security_group['id'], security_group_rule['id']) if options[:json] puts as_json(json_response, options) return 0 end display_name = (security_group_rule['name'].to_s != '') ? security_group_rule['name'] : security_group_rule['id'].to_s print_green_success "Deleted security group rule #{display_name}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
unuse(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1121 def unuse(args) use(args + ['--none']) end
update(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 398 def update(args) params = {} options = {:options => {}} tenants = nil group_access_all = nil group_access_list = nil group_defaults_list = nil optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [options]") opts.on( '--name Name', String, "Name of the security group" ) do |val| options[:options]['name'] = val end opts.on( '--description Description', String, "Description of the security group" ) do |val| options[:options]['description'] = val end opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val| group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '' end opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it group_access_list = [] else group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it group_defaults_list = [] else group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list| if list.size == 1 && list[0] == 'null' # hacky way to clear it options['tenants'] = [] else options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end end opts.on('--can-manage LIST', Array, "Tenant Can Manage, comma separated list of account IDs that can manage") do |list| options['canManage'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq end opts.on('--visibility [private|public]', String, "Visibility") do |val| options['visibility'] = val end opts.on('--active [on|off]', String, "Can be used to disable a security group") do |val| options[:options]['active'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '' end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) opts.footer = "Update a security group." + "\n" + "[security-group] is required. This is the name or id of the security group." end optparse.parse!(args) if args.count != 1 raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? # construct payload passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload['securityGroup'].deep_merge!(passed_options) unless passed_options.empty? else # prompt for resource folder options payload = { 'securityGroup' => { } } # allow arbitrary -O options payload['securityGroup'].deep_merge!(passed_options) unless passed_options.empty? # Group Access if group_access_all != nil payload['resourcePermissions'] ||= {} payload['resourcePermissions']['all'] = group_access_all end if group_access_list != nil payload['resourcePermissions'] ||= {} payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id| site = {"id" => site_id.to_i} if group_defaults_list && group_defaults_list.include?(site_id) site["default"] = true end site end end # Tenants if options['tenants'] || options['canManage'] payload['tenantPermissions'] = {} payload['tenantPermissions']['accounts'] = ((options['tenants'] || []) + (options['canManage'] || [])).uniq payload['tenantPermissions']['canManageAccounts'] = options['canManage'] if options['canManage'] end # Visibility if options['visibility'] != nil payload['securityGroup']['visibility'] = options['visibility'] end # Active if options['active'] != nil payload['securityGroup']['active'] = options['active'] end if payload['securityGroup'].empty? && payload['tenantPermissions'].nil? && payload['resourcePermissions'].nil? raise_command_error "Specify at least one option to update.\n#{optparse}" end end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_groups_interface.dry.update(security_group['id'], payload) return 0 end json_response = @security_groups_interface.update(security_group['id'], payload) if options[:json] puts as_json(json_response, options) return 0 end print_green_success "Updated security group #{json_response['securityGroup']['name']}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
update_rule(args)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 947 def update_rule(args) params = {} options = {:options => {}} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[security-group] [rule]") opts.on( '--name VALUE', String, "Name of the rule" ) do |val| options[:options]['name'] = val end opts.on( '--direction VALUE', String, "Direction" ) do |val| options[:options]['direction'] = val end opts.on( '--rule-type VALUE', String, "Rule Type" ) do |val| options[:options]['ruleType'] = val end opts.on( '--protocol VALUE', String, "Protocol" ) do |val| options[:options]['protocol'] = val end opts.on( '--port-range VALUE', String, "Port Range" ) do |val| options[:options]['portRange'] = val end opts.on( '--source-type VALUE', String, "Source Type" ) do |val| options[:options]['sourceType'] = val end opts.on( '--source VALUE', String, "Source" ) do |val| options[:options]['source'] = val end opts.on( '--source-group VALUE', String, "Source Security Group" ) do |val| options[:options]['sourceGroup'] = val end opts.on( '--source-tier VALUE', String, "Source Tier" ) do |val| options[:options]['sourceTier'] = val end opts.on( '--destination-type VALUE', String, "Destination Type" ) do |val| options[:options]['destinationType'] = val end opts.on( '--destination VALUE', String, "Destination" ) do |val| options[:options]['destination'] = val end opts.on( '--destination-group VALUE', String, "Destination Security Group" ) do |val| options[:options]['destinationGroup'] = val end opts.on( '--destination-tier VALUE', String, "Destination Tier" ) do |val| options[:options]['destinationTier'] = val end build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote]) opts.footer = "Update a security group rule." + "\n" + "[security-group] is required. This is the name or id of the security group." + "\n" "[rule] is required. This is the name or id of the security group rule." end optparse.parse!(args) if args.count != 2 raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}" end connect(options) begin security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? #security_group_rule = find_security_group_rule_by_id(security_group['id'], args[1]) #return 1 if security_group_rule.nil? security_group_rule = nil if security_group['rules'] matching_rules = [] if args[1].to_s =~ /\A\d{1,}\Z/ matching_rules = security_group['rules'].select {|it| it['id'].to_s == args[1].to_s } else matching_rules = security_group['rules'].select {|it| it['name'] == args[1].to_s } end if matching_rules.size > 1 print_red_alert "#{matching_rules.size} security group rules found by name '#{args[1]}'" rows = matching_rules.collect do |it| {id: it['id'], name: it['name']} end puts as_pretty_table(rows, [:id, :name], {color:red}) return 1 else security_group_rule = matching_rules[0] end end if security_group_rule.nil? print_red_alert "Security group rule not found for '#{args[1]}'" return 1 end passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {} payload = nil if options[:payload] payload = options[:payload] payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty? else # prompt for resource folder options payload = { 'rule' => { } } payload.deep_merge!({'rule' => passed_options}) unless passed_options.empty? if passed_options.empty? raise_command_error "Specify at least one option to update.\n#{optparse}" end end @security_groups_interface.setopts(options) if options[:dry_run] print_dry_run @security_group_rules_interface.dry.update(security_group['id'], security_group_rule['id'], payload) return 0 end json_response = @security_group_rules_interface.update(security_group['id'], security_group_rule['id'], payload) if options[:json] puts as_json(json_response, options) return 0 end security_group_rule = json_response['rule'] display_name = (security_group_rule['name'].to_s != '') ? security_group_rule['name'] : security_group_rule['id'].to_s print_green_success "Updated security group rule #{display_name}" get([security_group['id']]) return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
use(args)
click to toggle source
JD: still need this??
# File lib/morpheus/cli/commands/security_groups.rb, line 1073 def use(args) options = {} optparse = Morpheus::Cli::OptionParser.new do |opts| opts.banner = subcommand_usage("[id] [--none]") opts.on('--none','--none', "Do not use an active group.") do |json| options[:unuse] = true end build_common_options(opts, options, []) end optparse.parse!(args) if args.length < 1 && !options[:unuse] puts optparse return end connect(options) begin if options[:unuse] if @active_security_group[@appliance_name.to_sym] @active_security_group.delete(@appliance_name.to_sym) end ::Morpheus::Cli::SecurityGroups.save_security_group(@active_security_group) unless options[:quiet] print cyan puts "Switched to no active security group." print reset end print reset return # exit 0 end security_group = find_security_group_by_name_or_id(args[0]) return 1 if security_group.nil? if !security_group.nil? @active_security_group[@appliance_name.to_sym] = security_group['id'] ::Morpheus::Cli::SecurityGroups.save_security_group(@active_security_group) puts cyan, "Using Security Group #{args[0]}", reset else puts red, "Security Group not found", reset end return 0 rescue RestClient::Exception => e print_rest_exception(e, options) exit 1 end end
Private Instance Methods
find_resource_pool_by_id(cloud_id, id)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1212 def find_resource_pool_by_id(cloud_id, id) begin json_response = @cloud_resource_pools_interface.get(cloud_id, id.to_i) return json_response['resourcePool'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Resource Pool not found by id #{id}" return nil else raise e end end end
find_resource_pool_by_name(cloud_id, name)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1226 def find_resource_pool_by_name(cloud_id, name) json_response = @cloud_resource_pools_interface.list(cloud_id, {name: name.to_s}) resource_pools = json_response['resourcePools'] if resource_pools.empty? print_red_alert "Resource Pool not found by name #{name}" return nil elsif resource_pools.size > 1 matching_resource_pools = resource_pools.select { |it| name && (it['name'] == name || it['externalId'] == name) } if matching_resource_pools.size == 1 return matching_resource_pools[0] end print_red_alert "#{resource_pools.size} resource pools found by name #{name}" rows = resource_pools.collect do |it| {id: it['id'], name: it['name']} end print "\n" puts as_pretty_table(rows, [:id, :name], {color:red}) return nil else resource_pool = resource_pools[0] # merge in tenants map if json_response['tenants'] && json_response['tenants'][resource_pool['id']] resource_pool['tenants'] = json_response['tenants'][resource_pool['id']] end return resource_pool end end
find_resource_pool_by_name_or_id(cloud_id, val)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1204 def find_resource_pool_by_name_or_id(cloud_id, val) if val.to_s =~ /\A\d{1,}\Z/ return find_resource_pool_by_id(cloud_id, val) else return find_resource_pool_by_name(cloud_id, val) end end
find_security_group_by_id(id)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1158 def find_security_group_by_id(id) begin json_response = @security_groups_interface.get(id.to_i) return json_response['securityGroup'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Security Group not found by id #{id}" return nil else raise e end end end
find_security_group_by_name(name)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1172 def find_security_group_by_name(name) json_response = @security_groups_interface.list({name: name.to_s}) security_groups = json_response['securityGroups'] if security_groups.empty? print_red_alert "Security Group not found by name #{name}" return nil elsif security_groups.size > 1 print_red_alert "#{security_groups.size} security groups found by name #{name}" rows = security_groups.collect do |it| {id: it['id'], name: it['name']} end puts as_pretty_table(rows, [:id, :name], {color:red}) return nil else return security_groups[0] end end
find_security_group_by_name_or_id(val)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1150 def find_security_group_by_name_or_id(val) if val.to_s =~ /\A\d{1,}\Z/ return find_security_group_by_id(val) else return find_security_group_by_name(val) end end
find_security_group_rule_by_id(security_group_id, id)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1190 def find_security_group_rule_by_id(security_group_id, id) begin json_response = @security_groups_interface.get(security_group_id.to_i, id.to_i) return json_response['rule'] rescue RestClient::Exception => e if e.response && e.response.code == 404 print_red_alert "Security Group Rule not found by id #{id}" return nil else raise e end end end
prompt_security_group_custom_options(options, cloud, resource_pool_id=nil)
click to toggle source
# File lib/morpheus/cli/commands/security_groups.rb, line 1254 def prompt_security_group_custom_options(options, cloud, resource_pool_id=nil) custom_options_values = {} # Custom Options prompt # securityServer is no longer used, it has been replaced by networkServer, # default to the cloud type code, since it's the same... # no optionTypes returned here, so hard coded by type # The API used to return securityServer which could be fetched to get its optionTypes if cloud['securityServer'] sec_server = @network_security_servers.get(cloud['securityServer']['id'])['networkSecurityServer'] if sec_server['type'] v_prompt = Morpheus::Cli::OptionTypes.prompt(sec_server['type']['optionTypes'], options[:options], @api_client, {zoneId: cloud['id']}) custom_options_values.deep_merge!(v_prompt) end else network_server_type = cloud['networkServer'] ? cloud['networkServer']['type'] : (cloud['securityServer'] ? cloud['securityServer']['type'] : cloud["zoneType"]["code"]) if network_server_type == 'amazon' if cloud['config'] && !cloud['config']['vpc'].to_s.empty? custom_options_values.deep_merge!({'customOptions' => {'vpc' => cloud['config']['vpc']} }) else options[:options].deep_merge!({'customOptions' => {'vpc' => resource_pool_id} }) if resource_pool_id custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'vpc', 'fieldLabel' => 'VPC', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true}) end elsif network_server_type == 'azure' || network_server_type == 'azurestack' if cloud['config'] && !cloud['config']['resourceGroup'].to_s.empty? custom_options_values.deep_merge!({'customOptions' => {'resourceGroup' => cloud['config']['resourceGroup']} }) else options[:options].deep_merge!({'customOptions' => {'resourceGroup' => resource_pool_id} }) if resource_pool_id custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourceGroup', 'fieldLabel' => 'Resource Group', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true, 'config' => {'valueField' => 'externalId'}}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true}) end elsif network_server_type == 'openstack' || network_server_type == 'opentelekom' || network_server_type == 'huawei' if cloud['config'] && !cloud['config']['resourcePoolId'].to_s.empty? custom_options_values.deep_merge!({'customOptions' => {'resourcePoolId' => cloud['config']['resourcePoolId']} }) else options[:options].deep_merge!({'customOptions' => {'resourcePoolId' => resource_pool_id} }) if resource_pool_id custom_options_values = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => 'customOptions', 'fieldName' => 'resourcePoolId', 'fieldLabel' => 'Resource Pool', 'type' => 'select', 'optionSource' => 'zonePools', 'required' => true}], options[:options], @api_client, {zoneId: cloud['id'], ignoreDefaultPool: true}) end end end return custom_options_values end