You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by ma...@redhat.com on 2011/06/10 16:43:54 UTC
[PATCH 1/3] Implements 'firewalls' - ec2 security groups
From: marios <ma...@redhat.com>
Signed-off-by: marios <ma...@redhat.com>
---
server/Gemfile | 3 +-
server/deltacloud.rb | 2 +
server/lib/deltacloud/base_driver/base_driver.rb | 14 ++-
server/lib/deltacloud/base_driver/features.rb | 8 +-
server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 149 +++++++++++++++++++++-
server/lib/deltacloud/models/bucket.rb | 2 +-
server/lib/deltacloud/models/firewall.rb | 22 +++
server/lib/deltacloud/models/firewall_rule.rb | 23 ++++
server/public/javascripts/application.js | 63 +++++++--
server/server.rb | 112 ++++++++++++++++
server/views/firewalls/index.html.haml | 25 ++++
server/views/firewalls/index.xml.haml | 23 ++++
server/views/firewalls/new.html.haml | 11 ++
server/views/firewalls/new_rule.html.haml | 26 ++++
server/views/firewalls/show.html.haml | 44 +++++++
server/views/firewalls/show.xml.haml | 21 +++
16 files changed, 522 insertions(+), 26 deletions(-)
create mode 100644 server/lib/deltacloud/models/firewall.rb
create mode 100644 server/lib/deltacloud/models/firewall_rule.rb
create mode 100644 server/views/firewalls/index.html.haml
create mode 100644 server/views/firewalls/index.xml.haml
create mode 100644 server/views/firewalls/new.html.haml
create mode 100644 server/views/firewalls/new_rule.html.haml
create mode 100644 server/views/firewalls/show.html.haml
create mode 100644 server/views/firewalls/show.xml.haml
diff --git a/server/Gemfile b/server/Gemfile
index 3ab3d5c..ee5f805 100644
--- a/server/Gemfile
+++ b/server/Gemfile
@@ -15,7 +15,8 @@ group :azure do
end
group :ec2 do
- gem 'aws'
+ gem 'aws', ">= 2.5.4"
+
end
group :gogrid do
diff --git a/server/deltacloud.rb b/server/deltacloud.rb
index 7caf34f..5628e31 100644
--- a/server/deltacloud.rb
+++ b/server/deltacloud.rb
@@ -36,6 +36,8 @@ require 'deltacloud/models/storage_volume'
require 'deltacloud/models/bucket'
require 'deltacloud/models/blob'
require 'deltacloud/models/load_balancer'
+require 'deltacloud/models/firewall'
+require 'deltacloud/models/firewall_rule'
require 'deltacloud/validation'
require 'deltacloud/helpers'
diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
index 2c780d9..7f8bd65 100644
--- a/server/lib/deltacloud/base_driver/base_driver.rb
+++ b/server/lib/deltacloud/base_driver/base_driver.rb
@@ -149,7 +149,12 @@ module Deltacloud
# def keys(credentials, opts)
# def create_key(credentials, opts)
# def destroy_key(credentials, opts)
-
+ #
+ # def firewalls(credentials, opts)
+ # def create_firewall(credentials, opts)
+ # def delete_firewall(credentials, opts)
+ # def create_firewall_rule(credentials, opts)
+ # def delete_firewall_rule(credentials, opts)
def realm(credentials, opts)
realms = realms(credentials, opts).first if has_capability?(:realms)
end
@@ -183,8 +188,12 @@ module Deltacloud
keys(credentials, opts).first if has_capability?(:keys)
end
+ def firewall(credentials, opts={})
+ firewalls(credentials, opts).first if has_capability?(:firewalls)
+ end
+
MEMBER_SHOW_METHODS =
- [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key ]
+ [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key, :firewall ]
def has_capability?(capability)
if MEMBER_SHOW_METHODS.include?(capability.to_sym)
@@ -194,7 +203,6 @@ module Deltacloud
end
end
-
def filter_on(collection, attribute, opts)
return collection if opts.nil?
return collection if opts[attribute].nil?
diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
index b5bc3ee..4a2f1f8 100644
--- a/server/lib/deltacloud/base_driver/features.rb
+++ b/server/lib/deltacloud/base_driver/features.rb
@@ -187,11 +187,11 @@ module Deltacloud
end
end
- declare_feature :instances, :security_group do
- description "Put instance in one or more security groups on launch"
+ declare_feature :instances, :firewall do
+ description "Put instance in one or more firewalls (security groups) on launch"
operation :create do
- param :security_group, :array, :optional, [],
- "Array of security group names"
+ param :firewalls, :array, :optional, nil, "Array of firewall ID strings"
+ "Array of firewall (security group) id"
end
end
diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
index 4edd989..fbf39f1 100644
--- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
+++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
@@ -33,12 +33,13 @@ module Deltacloud
class EC2Driver < Deltacloud::BaseDriver
def supported_collections
- DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses ]
+
+ DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses, :firewalls ]
end
feature :instances, :user_data
feature :instances, :authentication_key
- feature :instances, :security_group
+ feature :instances, :firewall
feature :instances, :instance_count
feature :images, :owner_id
feature :buckets, :bucket_location
@@ -201,7 +202,7 @@ module Deltacloud
instance_options.merge!(:key_name => opts[:keyname]) if opts[:keyname]
instance_options.merge!(:availability_zone => opts[:realm_id]) if opts[:realm_id]
instance_options.merge!(:instance_type => opts[:hwp_id]) if opts[:hwp_id] && opts[:hwp_id].length > 0
- instance_options.merge!(:group_ids => opts[:security_group]) if opts[:security_group]
+ instance_options.merge!(:group_ids => opts[:firewalls]) if opts[:firewalls]
instance_options.merge!(
:min_count => opts[:instance_count],
:max_count => opts[:instance_count]
@@ -571,6 +572,73 @@ module Deltacloud
end
end
+#--
+#FIREWALLS - ec2 security groups
+#--
+ def firewalls(credentials, opts={})
+ ec2 = new_client(credentials)
+ the_firewalls = []
+ groups = []
+ safely do
+ if opts[:id]
+ groups = ec2.describe_security_groups([opts[:id]])
+ else
+ groups = ec2.describe_security_groups()
+ end
+ end
+ groups.each do |security_group|
+ the_firewalls << convert_security_group(security_group)
+ end
+ the_firewalls
+ end
+
+#--
+#Create firewall
+#--
+ def create_firewall(credentials, opts={})
+ ec2 = new_client(credentials)
+ safely do
+ ec2.create_security_group(opts["name"], opts["description"])
+ end
+ Firewall.new( { :id=>opts["name"], :name=>opts["name"],
+ :description => opts["description"], :owner_id => "", :rules => [] } )
+ end
+
+#--
+#Delete firewall
+#--
+ def delete_firewall(credentials, opts={})
+ ec2 = new_client(credentials)
+ safely do
+ ec2.delete_security_group(opts["id"])
+ end
+ end
+#--
+#Create firewall rule
+#--
+ def create_firewall_rule(credentials, opts={})
+ ec2 = new_client(credentials)
+ groups = []
+ opts['groups'].each do |k,v|
+ groups << {"group_name" => k, "owner" =>v}
+ end
+ safely do
+ ec2.manage_security_group_ingress(opts['id'], opts['from_port'], opts['to_port'], opts['protocol'],
+ "authorize", opts['addresses'], groups)
+ end
+ end
+#--
+#Delete firewall rule
+#--
+ def delete_firewall_rule(credentials, opts={})
+ ec2 = new_client(credentials)
+ firewall = opts[:id]
+ protocol, from_port, to_port, addresses, groups = firewall_rule_params(opts[:rule_id])
+ safely do
+ ec2.manage_security_group_ingress(firewall, from_port, to_port, protocol, "revoke", addresses, groups)
+ end
+ end
+
def valid_credentials?(credentials)
retval = true
begin
@@ -764,6 +832,81 @@ module Deltacloud
balancer
end
+ #generate uid from firewall rule parameters (amazon doesn't do this for us
+ def firewall_rule_id(user_id, protocol, from_port, to_port, sources)
+ sources_string = ""
+ sources.each do |source|
+ sources_string<<"@"
+ source.each_pair do |key,value|
+ sources_string<< "#{value},"
+ end
+ sources_string.chomp!(",")
+ end
+ #sources_string is @group,297467797945,test@address,ipv4,10.1.1.1,24 etc
+ id_string = "#{user_id}~#{protocol}~#{from_port}~#{to_port}~#{sources_string}"
+ end
+
+ #extract params from uid
+ def firewall_rule_params(id)
+ #user_id~protocol~from_port~to_port~sources_string
+ params = id.split("~")
+ protocol = params[1]
+ from_port = params[2]
+ to_port = params[3]
+ sources = params[4].split("@")
+ sources.shift #first match is ""
+ addresses = []
+ groups = []
+ #@group,297467797945,test@address,ipv4,10.1.1.1,24@address,ipv4,192.168.1.1,24
+ sources.each do |source|
+ current = source.split(",")
+ type = current[0]
+ case type
+ when 'group'
+ #group,297467797945,test
+ owner = current[1]
+ name = current[2]
+ groups << {'group_name' => name, 'owner' => owner}
+ when 'address'
+ #address,ipv4,10.1.1.1,24
+ address = current[2]
+ address<<"/#{current[3]}"
+ addresses << address
+ end
+ end
+ return protocol, from_port, to_port, addresses, groups
+ end
+
+ #Convert ec2 security group to server/lib/deltacloud/models/firewall
+ def convert_security_group(security_group)
+ rules = []
+ security_group[:aws_perms].each do |perm|
+ sources = []
+ perm[:groups].each do |group|
+ sources << {:type => "group", :name => group[:group_name], :owner => group[:owner]}
+ end
+ perm[:ip_ranges].each do |ip|
+ sources << {:type => "address", :family=>"ipv4",
+ :address=>ip[:cidr_ip].split("/").first,
+ :prefix=>ip[:cidr_ip].split("/").last}
+ end
+ rule_id = firewall_rule_id(security_group[:aws_owner], perm[:protocol],
+ perm[:from_port] , perm[:to_port], sources)
+ rules << FirewallRule.new({:id => rule_id,
+ :allow_protocol => perm[:protocol],
+ :port_from => perm[:from_port],
+ :port_to => perm[:to_port],
+ :direction => 'ingress',
+ :sources => sources})
+ end
+ Firewall.new( { :id => security_group[:aws_group_name],
+ :name => security_group[:aws_group_name],
+ :description => security_group[:aws_description],
+ :owner_id => security_group[:aws_owner],
+ :rules => rules
+ } )
+ end
+
def convert_state(ec2_state)
case ec2_state
when "terminated"
diff --git a/server/lib/deltacloud/models/bucket.rb b/server/lib/deltacloud/models/bucket.rb
index e6b2b34..bef36ac 100644
--- a/server/lib/deltacloud/models/bucket.rb
+++ b/server/lib/deltacloud/models/bucket.rb
@@ -24,7 +24,7 @@ class Bucket < BaseModel
def to_hash
h = self.to_hash_original
- h[:blob_list] = self.blob_list.collect { |blob| { :id => blob,
+ h[:blob_list] = self.blob_list.collect { |blob| { :id => blob,
:href => "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/buckets/#{self.id}/#{blob.id}"}}
return h
end
diff --git a/server/lib/deltacloud/models/firewall.rb b/server/lib/deltacloud/models/firewall.rb
new file mode 100644
index 0000000..dc0ae3d
--- /dev/null
+++ b/server/lib/deltacloud/models/firewall.rb
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class Firewall < BaseModel
+ attr_accessor :name
+ attr_accessor :description
+ attr_accessor :owner_id
+ attr_accessor :rules
+end
\ No newline at end of file
diff --git a/server/lib/deltacloud/models/firewall_rule.rb b/server/lib/deltacloud/models/firewall_rule.rb
new file mode 100644
index 0000000..3959eb6
--- /dev/null
+++ b/server/lib/deltacloud/models/firewall_rule.rb
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class FirewallRule < BaseModel
+ attr_accessor :allow_protocol # tcp/udp/icmp
+ attr_accessor :port_from
+ attr_accessor :port_to
+ attr_accessor :sources
+ attr_accessor :direction #ingress egress
+end
diff --git a/server/public/javascripts/application.js b/server/public/javascripts/application.js
index 95c9bc2..703879c 100644
--- a/server/public/javascripts/application.js
+++ b/server/public/javascripts/application.js
@@ -19,10 +19,10 @@ $(document).ready(function() {
function more_fields()
{
- //increment the hidden input that captures how many meta_data are passed
- var meta_params = document.getElementsByName('meta_params')
+ //increment the hidden input that captures how many meta_data are passed
+ var meta_params = document.getElementsByName('meta_params')
current_number_params = eval(meta_params[0].value)+1
- meta_params[0].value = current_number_params
+ meta_params[0].value = current_number_params
var new_meta = document.getElementById('metadata_holder').cloneNode(true);
new_meta.id = 'metadata_holder' + current_number_params;
new_meta.style.display = 'block';
@@ -39,15 +39,50 @@ function more_fields()
function less_fields()
{
var meta_params = document.getElementsByName('meta_params')
- current_val = eval(meta_params[0].value)
- if (current_val == 0)
- {
- return;
- }
- else
- {
- var theDiv = document.getElementById('metadata_holder'+current_val)
- theDiv.parentNode.removeChild(theDiv)
- meta_params[0].value = eval(current_val)-1
- }
+ current_val = eval(meta_params[0].value)
+ if (current_val == 0)
+ {
+ return;
+ }
+ else
+ {
+ var theDiv = document.getElementById('metadata_holder'+current_val)
+ theDiv.parentNode.removeChild(theDiv)
+ meta_params[0].value = eval(current_val)-1
+ }
+}
+
+var addresses = 0;
+var groups = 0;
+function make_fields(type)
+{
+ form = document.getElementById("new_rule_form")
+ button = document.getElementById("submit_button")
+ if(type == "address")
+ {
+ name = "ip_address" + eval(++addresses)
+ create_rule_source_field(name, "Address " + eval(addresses) + " [use CIDR notation 0.0.0.0/0]", form, button)
+ }
+ else if(type == "group")
+ {
+ name = "group" + eval(++groups)
+ create_rule_source_field(name, "Name of group " + eval(groups), form, button)
+ name = "group" + eval(groups) + "owner"
+ create_rule_source_field(name, "Group " + eval(groups) + " owner (required)", form, button)
+ }
+}
+
+function create_rule_source_field(name, label, form, button)
+{
+ element = document.createElement("INPUT")
+ element.type = "input"
+ element.size = 35
+ element.name = name
+ text = document.createTextNode(label)
+ form.insertBefore(element, button)
+ form.insertBefore(text, element)
+ form.insertBefore(document.createElement('BR'), element)
+ form.insertBefore(document.createElement('BR'), button)
+ form.insertBefore(document.createElement('BR'), button)
+ form.insertBefore(document.createElement('BR'), button)
}
diff --git a/server/server.rb b/server/server.rb
index ba87c67..ae23263 100644
--- a/server/server.rb
+++ b/server/server.rb
@@ -948,3 +948,115 @@ collection :addresses do
end
end
+
+#html for creating a new firewall
+get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/firewalls/new" do
+ respond_to do |format|
+ format.html { haml :"firewalls/new" }
+ end
+end
+
+#html for creating a new firewall rule
+get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/firewalls/:firewall/new_rule" do
+ @firewall_name = params[:firewall]
+ respond_to do |format|
+ format.html {haml :"firewalls/new_rule" }
+ end
+end
+
+#FIREWALLS
+collection :firewalls do
+ description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
+ operation :index do
+ description 'List all firewalls'
+ with_capability :firewalls
+ control { filter_all(:firewalls) }
+ end
+
+ operation :show do
+ description 'Show details for a specific firewall - list all rules'
+ with_capability :firewall
+ param :id, :string, :required
+ control { show(:firewall) }
+ end
+
+ operation :create do
+ description 'Create a new firewall'
+ with_capability :create_firewall
+ param :name, :string, :required
+ param :description, :string, :required
+ control do
+ @firewall = driver.create_firewall(credentials, params )
+ respond_to do |format|
+ format.xml do
+ response.status = 201 # Created
+ haml :"firewalls/show"
+ end
+ format.html {haml :"firewalls/show"}
+ format.json {convert_to_json(:firewall, @firewall)}
+ end
+ end
+ end
+
+ operation :destroy do
+ description 'Delete a specified firewall - error if firewall has rules'
+ with_capability :delete_firewall
+ param :id, :string, :required
+ control do
+ driver.delete_firewall(credentials, params)
+ respond_to do |format|
+ format.xml { 204 }
+ format.json { 204 }
+ format.html { redirect(firewalls_url) }
+ end
+ end
+ end
+
+#create a new firewall rule - POST /api/firewalls/:firewall/rules
+ operation :rules, :method => :post, :member => true do
+ description 'Create a new firewall rule for the specified firewall'
+ param :firewall, :required, :string, [], "Name of firewall in which to apply this rule"
+ param :protocol, :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
+ param :from_port, :required, :string, [], "Start of port range for the rule"
+ param :to_port, :required, :string, [], "End of port range for the rule"
+ with_capability :create_firewall_rule
+ control do
+ #source IPs from params
+ addresses = params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
+ #source groups from params
+ groups = {}
+ max_groups = params.select{|k,v| k=~/^group/}.size/2
+ for i in (1..max_groups) do
+ groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
+ end
+ params.merge!( {'addresses' => addresses} ) ; params.merge!( {'groups' => groups} )
+ driver.create_firewall_rule(credentials, params)
+ @firewall = driver.firewall(credentials, {:id => params[:firewall]})
+ respond_to do |format|
+ format.html {haml :"firewalls/show"}
+ format.xml do
+ response.status = 201 #created
+ haml :"firewall/show"
+ end
+ format.json {convert_to_json(:firewall, @firewall)}
+ end
+ end
+ end
+
+#delete a firewall rule DELETE /api/firewalls/:firewall/rule - with param rule_id
+ operation :rule, :method => :delete, :member => true do
+ description 'Delete the specified firewall rule from the given firewall'
+ param :firewall, :required, :string
+ param :rule_id, :required, :string
+ with_capability :delete_firewall_rule
+ control do
+ driver.delete_firewall_rule(credentials, params)
+ respond_to do |format|
+ format.html {redirect firewall_url(params[:id])}
+ format.xml {204}
+ format.json {204}
+ end
+ end
+ end
+
+end #firewalls
diff --git a/server/views/firewalls/index.html.haml b/server/views/firewalls/index.html.haml
new file mode 100644
index 0000000..3312a32
--- /dev/null
+++ b/server/views/firewalls/index.html.haml
@@ -0,0 +1,25 @@
+%h1 Firewalls
+%br
+%p
+ =link_to 'Create new firewall', "/api/firewalls/new"
+%table.display
+ %thead
+ %tr
+ %th Id
+ %th Name
+ %th Description
+ %th Owner ID
+ %th Rules
+ %tbody
+ - @firewalls.each do |firewall|
+ %tr
+ %td
+ = link_to firewall.id, firewall_url(firewall.id)
+ %td
+ = firewall.name
+ %td
+ = firewall.description
+ %td
+ = firewall.owner_id
+ %td
+ = link_to 'view rules', firewall_url(firewall.id)
diff --git a/server/views/firewalls/index.xml.haml b/server/views/firewalls/index.xml.haml
new file mode 100644
index 0000000..f027785
--- /dev/null
+++ b/server/views/firewalls/index.xml.haml
@@ -0,0 +1,23 @@
+!!! XML
+%firewalls
+ - @firewalls.each do |firewall|
+ %firewall{:href => firewall_url(firewall.id), :id => firewall.id}
+ - firewall.attributes.select{ |attr| attr != :id && attr!= :rules}.each do |attribute|
+ - haml_tag("#{attribute}".tr('-', '_'), :<) do
+ - if [:name, :description].include?(attribute)
+ =cdata do
+ - haml_concat firewall.send(attribute)
+ - else
+ - haml_concat firewall.send(attribute)
+ %rules
+ - firewall.rules.each do |rule|
+ %rule{:id => rule.id}
+ - rule.attributes.select{|attr| attr != :sources && attr != :id}.each do |rule_attrib|
+ - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do
+ - haml_concat rule.send(rule_attrib)
+ %sources
+ - rule.sources.each do |source|
+ - if source[:type] == "group"
+ %source{:name => source[:name], :type=> source[:type], :owner=> source[:owner]}
+ - else
+ %source{:prefix => source[:prefix], :address=> source[:address], :family=>source[:family], :type => source[:type]}
\ No newline at end of file
diff --git a/server/views/firewalls/new.html.haml b/server/views/firewalls/new.html.haml
new file mode 100644
index 0000000..4a230a6
--- /dev/null
+++ b/server/views/firewalls/new.html.haml
@@ -0,0 +1,11 @@
+%h1 New Firewall
+
+%form{:action => firewalls_url, :method => :post}
+ %label
+ Firewall Name
+ %input{:name => 'name', :size => 25}/
+ %br
+ %label
+ Firewall Description
+ %input{:name => 'description', :size => 100}/
+ %input{:type => :submit, :name => "commit", :value=>"create"}
\ No newline at end of file
diff --git a/server/views/firewalls/new_rule.html.haml b/server/views/firewalls/new_rule.html.haml
new file mode 100644
index 0000000..b25206a
--- /dev/null
+++ b/server/views/firewalls/new_rule.html.haml
@@ -0,0 +1,26 @@
+%h1 New Firewall Rule
+
+%form{ :action => "#{firewall_url(@firewall_name)}/rules", :id => "new_rule_form", :method => :post, :enctype => 'multipart/form-data'}
+ %label
+ Protocol:
+ %br
+ %input{ :name => 'protocol', :size => 10}/
+ %br
+ %br
+ %label
+ From port:
+ %br
+ %input{ :name => 'from_port', :size => 10}/
+ %br
+ %br
+ To port:
+ %br
+ %input{ :name => 'to_port', :size => 10}/
+ %br
+ %br
+ %a{ :href => "javascript:;", :onclick => "make_fields('address');"} Add source IP address
+ %br
+ %a{ :href => "javascript:;", :onclick => "make_fields('group');"} Add source group
+ %br
+ %br
+ %input{ :type => :submit, :id => "submit_button", :name => "commit", :value => "create"}/
diff --git a/server/views/firewalls/show.html.haml b/server/views/firewalls/show.html.haml
new file mode 100644
index 0000000..b77aaa4
--- /dev/null
+++ b/server/views/firewalls/show.html.haml
@@ -0,0 +1,44 @@
+%h1 Firewall
+%h2
+ = @firewall.id
+%dl
+ %di
+ %dt Name
+ %dd
+ = @firewall.name
+ %dt Owner
+ %dd
+ = @firewall.owner_id
+ %dt Description
+ %dd
+ = @firewall.description
+
+%h2
+ Rules
+ %br
+ %p
+ =link_to 'Create a new rule', "/api/firewalls/#{@firewall.name}/new_rule"
+%dl
+ - @firewall.rules.each do |rule|
+ %di
+ Rule
+ - rule.attributes.select{|attr| attr != :sources}.each do |attrib|
+ %dt #{attrib}
+ %dd
+ = rule.send(attrib)
+ %dt sources
+ %dd
+ - rule.sources.each do |source|
+ - if source[:type] == "group"
+ type: #{source[:type]}, name: #{source[:name]}, owner: #{source[:owner]}
+ %br
+ - else
+ type: #{source[:type]}, family: #{source[:family]}, address: #{source[:address]}, prefix: #{source[:prefix]}
+ %br
+ %dd
+ %form{ :action => "#{firewall_url(@firewall.name)}/rule", :method => :post}
+ %input{:type => "hidden", :name => "_method", :value => "delete"}
+ %input{:type => "hidden", :name => "rule_id", :value => rule.id}
+ %input{:type => :submit, :value => "Delete Rule"}
+ %dd
+ = link_to_action 'Delete Firewall', destroy_firewall_url(@firewall.name), :delete
diff --git a/server/views/firewalls/show.xml.haml b/server/views/firewalls/show.xml.haml
new file mode 100644
index 0000000..9d1fc48
--- /dev/null
+++ b/server/views/firewalls/show.xml.haml
@@ -0,0 +1,21 @@
+!!! XML
+%firewall{:href => firewall_url(@firewall.id), :id => @firewall.id}
+ - @firewall.attributes.select{ |attr| attr != :id && attr!= :rules}.each do |attribute|
+ - haml_tag("#{attribute}".tr('-', '_'), :<) do
+ - if [:name, :description].include?(attribute)
+ =cdata do
+ - haml_concat @firewall.send(attribute)
+ - else
+ - haml_concat @firewall.send(attribute)
+ %rules
+ - @firewall.rules.each do |rule|
+ %rule{:id => rule.id}
+ - rule.attributes.select{|attr| attr != :sources && attr != :id}.each do |rule_attrib|
+ - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do
+ - haml_concat rule.send(rule_attrib)
+ %sources
+ - rule.sources.each do |source|
+ - if source[:type] == "group"
+ %source{:name => source[:name], :type=> source[:type], :owner=>source[:owner]}
+ - else
+ %source{:prefix => source[:prefix], :address=> source[:address], :family=>source[:family], :type => source[:type]}
\ No newline at end of file
--
1.7.3.4
Re: [PATCH 1/3] Implements 'firewalls' - ec2 security groups
Posted by Michal Fojtik <mf...@redhat.com>.
On Jun 10, 2011, at 4:43 PM, marios@redhat.com wrote:
ACK.
A few minor indentation/whitespace doubts inline.
-- Michal
> From: marios <ma...@redhat.com>
>
>
> Signed-off-by: marios <ma...@redhat.com>
> ---
> server/Gemfile | 3 +-
> server/deltacloud.rb | 2 +
> server/lib/deltacloud/base_driver/base_driver.rb | 14 ++-
> server/lib/deltacloud/base_driver/features.rb | 8 +-
> server/lib/deltacloud/drivers/ec2/ec2_driver.rb | 149 +++++++++++++++++++++-
> server/lib/deltacloud/models/bucket.rb | 2 +-
> server/lib/deltacloud/models/firewall.rb | 22 +++
> server/lib/deltacloud/models/firewall_rule.rb | 23 ++++
> server/public/javascripts/application.js | 63 +++++++--
> server/server.rb | 112 ++++++++++++++++
> server/views/firewalls/index.html.haml | 25 ++++
> server/views/firewalls/index.xml.haml | 23 ++++
> server/views/firewalls/new.html.haml | 11 ++
> server/views/firewalls/new_rule.html.haml | 26 ++++
> server/views/firewalls/show.html.haml | 44 +++++++
> server/views/firewalls/show.xml.haml | 21 +++
> 16 files changed, 522 insertions(+), 26 deletions(-)
> create mode 100644 server/lib/deltacloud/models/firewall.rb
> create mode 100644 server/lib/deltacloud/models/firewall_rule.rb
> create mode 100644 server/views/firewalls/index.html.haml
> create mode 100644 server/views/firewalls/index.xml.haml
> create mode 100644 server/views/firewalls/new.html.haml
> create mode 100644 server/views/firewalls/new_rule.html.haml
> create mode 100644 server/views/firewalls/show.html.haml
> create mode 100644 server/views/firewalls/show.xml.haml
>
> diff --git a/server/Gemfile b/server/Gemfile
> index 3ab3d5c..ee5f805 100644
> --- a/server/Gemfile
> +++ b/server/Gemfile
> @@ -15,7 +15,8 @@ group :azure do
> end
>
> group :ec2 do
> - gem 'aws'
> + gem 'aws', ">= 2.5.4"
> +
> end
>
> group :gogrid do
> diff --git a/server/deltacloud.rb b/server/deltacloud.rb
> index 7caf34f..5628e31 100644
> --- a/server/deltacloud.rb
> +++ b/server/deltacloud.rb
> @@ -36,6 +36,8 @@ require 'deltacloud/models/storage_volume'
> require 'deltacloud/models/bucket'
> require 'deltacloud/models/blob'
> require 'deltacloud/models/load_balancer'
> +require 'deltacloud/models/firewall'
> +require 'deltacloud/models/firewall_rule'
>
> require 'deltacloud/validation'
> require 'deltacloud/helpers'
> diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
> index 2c780d9..7f8bd65 100644
> --- a/server/lib/deltacloud/base_driver/base_driver.rb
> +++ b/server/lib/deltacloud/base_driver/base_driver.rb
> @@ -149,7 +149,12 @@ module Deltacloud
> # def keys(credentials, opts)
> # def create_key(credentials, opts)
> # def destroy_key(credentials, opts)
> -
> + #
> + # def firewalls(credentials, opts)
> + # def create_firewall(credentials, opts)
> + # def delete_firewall(credentials, opts)
> + # def create_firewall_rule(credentials, opts)
> + # def delete_firewall_rule(credentials, opts)
I don't think this change is necessary.
> def realm(credentials, opts)
> realms = realms(credentials, opts).first if has_capability?(:realms)
> end
> @@ -183,8 +188,12 @@ module Deltacloud
> keys(credentials, opts).first if has_capability?(:keys)
> end
>
> + def firewall(credentials, opts={})
> + firewalls(credentials, opts).first if has_capability?(:firewalls)
> + end
> +
> MEMBER_SHOW_METHODS =
> - [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key ]
> + [ :realm, :image, :instance, :storage_volume, :bucket, :blob, :key, :firewall ]
>
> def has_capability?(capability)
> if MEMBER_SHOW_METHODS.include?(capability.to_sym)
> @@ -194,7 +203,6 @@ module Deltacloud
> end
> end
>
> -
> def filter_on(collection, attribute, opts)
> return collection if opts.nil?
> return collection if opts[attribute].nil?
> diff --git a/server/lib/deltacloud/base_driver/features.rb b/server/lib/deltacloud/base_driver/features.rb
> index b5bc3ee..4a2f1f8 100644
> --- a/server/lib/deltacloud/base_driver/features.rb
> +++ b/server/lib/deltacloud/base_driver/features.rb
> @@ -187,11 +187,11 @@ module Deltacloud
> end
> end
>
> - declare_feature :instances, :security_group do
> - description "Put instance in one or more security groups on launch"
> + declare_feature :instances, :firewall do
> + description "Put instance in one or more firewalls (security groups) on launch"
> operation :create do
> - param :security_group, :array, :optional, [],
> - "Array of security group names"
> + param :firewalls, :array, :optional, nil, "Array of firewall ID strings"
> + "Array of firewall (security group) id"
> end
> end
>
> diff --git a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
> index 4edd989..fbf39f1 100644
> --- a/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
> +++ b/server/lib/deltacloud/drivers/ec2/ec2_driver.rb
> @@ -33,12 +33,13 @@ module Deltacloud
> class EC2Driver < Deltacloud::BaseDriver
>
> def supported_collections
> - DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses ]
> +
> + DEFAULT_COLLECTIONS + [ :keys, :buckets, :load_balancers, :addresses, :firewalls ]
> end
>
> feature :instances, :user_data
> feature :instances, :authentication_key
> - feature :instances, :security_group
> + feature :instances, :firewall
> feature :instances, :instance_count
> feature :images, :owner_id
> feature :buckets, :bucket_location
> @@ -201,7 +202,7 @@ module Deltacloud
> instance_options.merge!(:key_name => opts[:keyname]) if opts[:keyname]
> instance_options.merge!(:availability_zone => opts[:realm_id]) if opts[:realm_id]
> instance_options.merge!(:instance_type => opts[:hwp_id]) if opts[:hwp_id] && opts[:hwp_id].length > 0
> - instance_options.merge!(:group_ids => opts[:security_group]) if opts[:security_group]
> + instance_options.merge!(:group_ids => opts[:firewalls]) if opts[:firewalls]
> instance_options.merge!(
> :min_count => opts[:instance_count],
> :max_count => opts[:instance_count]
> @@ -571,6 +572,73 @@ module Deltacloud
> end
> end
>
> +#--
> +#FIREWALLS - ec2 security groups
> +#--
> + def firewalls(credentials, opts={})
> + ec2 = new_client(credentials)
> + the_firewalls = []
> + groups = []
> + safely do
> + if opts[:id]
> + groups = ec2.describe_security_groups([opts[:id]])
> + else
> + groups = ec2.describe_security_groups()
> + end
> + end
> + groups.each do |security_group|
> + the_firewalls << convert_security_group(security_group)
> + end
> + the_firewalls
> + end
Here you're using 4 spaces for indentation.
> +
> +#--
> +#Create firewall
> +#--
> + def create_firewall(credentials, opts={})
> + ec2 = new_client(credentials)
Here you're using 2 spaces. I would prefer to use just 2 spaces ;-)
> + safely do
> + ec2.create_security_group(opts["name"], opts["description"])
> + end
> + Firewall.new( { :id=>opts["name"], :name=>opts["name"],
> + :description => opts["description"], :owner_id => "", :rules => [] } )
> + end
> +
> +#--
> +#Delete firewall
> +#--
> + def delete_firewall(credentials, opts={})
> + ec2 = new_client(credentials)
> + safely do
> + ec2.delete_security_group(opts["id"])
> + end
> + end
> +#--
> +#Create firewall rule
> +#--
> + def create_firewall_rule(credentials, opts={})
> + ec2 = new_client(credentials)
> + groups = []
> + opts['groups'].each do |k,v|
> + groups << {"group_name" => k, "owner" =>v}
> + end
> + safely do
> + ec2.manage_security_group_ingress(opts['id'], opts['from_port'], opts['to_port'], opts['protocol'],
> + "authorize", opts['addresses'], groups)
> + end
> + end
> +#--
> +#Delete firewall rule
> +#--
> + def delete_firewall_rule(credentials, opts={})
> + ec2 = new_client(credentials)
> + firewall = opts[:id]
> + protocol, from_port, to_port, addresses, groups = firewall_rule_params(opts[:rule_id])
> + safely do
> + ec2.manage_security_group_ingress(firewall, from_port, to_port, protocol, "revoke", addresses, groups)
> + end
> + end
> +
> def valid_credentials?(credentials)
> retval = true
> begin
> @@ -764,6 +832,81 @@ module Deltacloud
> balancer
> end
>
> + #generate uid from firewall rule parameters (amazon doesn't do this for us
> + def firewall_rule_id(user_id, protocol, from_port, to_port, sources)
> + sources_string = ""
> + sources.each do |source|
> + sources_string<<"@"
> + source.each_pair do |key,value|
> + sources_string<< "#{value},"
> + end
> + sources_string.chomp!(",")
> + end
> + #sources_string is @group,297467797945,test@address,ipv4,10.1.1.1,24 etc
> + id_string = "#{user_id}~#{protocol}~#{from_port}~#{to_port}~#{sources_string}"
> + end
> +
> + #extract params from uid
> + def firewall_rule_params(id)
> + #user_id~protocol~from_port~to_port~sources_string
> + params = id.split("~")
> + protocol = params[1]
> + from_port = params[2]
> + to_port = params[3]
> + sources = params[4].split("@")
> + sources.shift #first match is ""
> + addresses = []
> + groups = []
> + #@group,297467797945,test@address,ipv4,10.1.1.1,24@address,ipv4,192.168.1.1,24
> + sources.each do |source|
> + current = source.split(",")
> + type = current[0]
> + case type
> + when 'group'
> + #group,297467797945,test
> + owner = current[1]
> + name = current[2]
> + groups << {'group_name' => name, 'owner' => owner}
> + when 'address'
> + #address,ipv4,10.1.1.1,24
> + address = current[2]
> + address<<"/#{current[3]}"
> + addresses << address
> + end
> + end
> + return protocol, from_port, to_port, addresses, groups
> + end
> +
> + #Convert ec2 security group to server/lib/deltacloud/models/firewall
> + def convert_security_group(security_group)
> + rules = []
> + security_group[:aws_perms].each do |perm|
> + sources = []
> + perm[:groups].each do |group|
> + sources << {:type => "group", :name => group[:group_name], :owner => group[:owner]}
> + end
> + perm[:ip_ranges].each do |ip|
> + sources << {:type => "address", :family=>"ipv4",
> + :address=>ip[:cidr_ip].split("/").first,
> + :prefix=>ip[:cidr_ip].split("/").last}
> + end
> + rule_id = firewall_rule_id(security_group[:aws_owner], perm[:protocol],
> + perm[:from_port] , perm[:to_port], sources)
> + rules << FirewallRule.new({:id => rule_id,
> + :allow_protocol => perm[:protocol],
> + :port_from => perm[:from_port],
> + :port_to => perm[:to_port],
> + :direction => 'ingress',
> + :sources => sources})
> + end
> + Firewall.new( { :id => security_group[:aws_group_name],
> + :name => security_group[:aws_group_name],
> + :description => security_group[:aws_description],
> + :owner_id => security_group[:aws_owner],
> + :rules => rules
> + } )
> + end
> +
> def convert_state(ec2_state)
> case ec2_state
> when "terminated"
> diff --git a/server/lib/deltacloud/models/bucket.rb b/server/lib/deltacloud/models/bucket.rb
> index e6b2b34..bef36ac 100644
> --- a/server/lib/deltacloud/models/bucket.rb
> +++ b/server/lib/deltacloud/models/bucket.rb
> @@ -24,7 +24,7 @@ class Bucket < BaseModel
>
> def to_hash
> h = self.to_hash_original
> - h[:blob_list] = self.blob_list.collect { |blob| { :id => blob,
> + h[:blob_list] = self.blob_list.collect { |blob| { :id => blob,
> :href => "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/buckets/#{self.id}/#{blob.id}"}}
> return h
> end
> diff --git a/server/lib/deltacloud/models/firewall.rb b/server/lib/deltacloud/models/firewall.rb
> new file mode 100644
> index 0000000..dc0ae3d
> --- /dev/null
> +++ b/server/lib/deltacloud/models/firewall.rb
> @@ -0,0 +1,22 @@
> +#
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements. See the NOTICE file distributed with
> +# this work for additional information regarding copyright ownership. The
> +# ASF licenses this file to you under the Apache License, Version 2.0 (the
> +# "License"); you may not use this file except in compliance with the
> +# License. You may obtain a copy of the License at
> +#
> +# http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
> +# License for the specific language governing permissions and limitations
> +# under the License.
> +
> +class Firewall < BaseModel
> + attr_accessor :name
> + attr_accessor :description
> + attr_accessor :owner_id
> + attr_accessor :rules
> +end
> \ No newline at end of file
> diff --git a/server/lib/deltacloud/models/firewall_rule.rb b/server/lib/deltacloud/models/firewall_rule.rb
> new file mode 100644
> index 0000000..3959eb6
> --- /dev/null
> +++ b/server/lib/deltacloud/models/firewall_rule.rb
> @@ -0,0 +1,23 @@
> +#
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements. See the NOTICE file distributed with
> +# this work for additional information regarding copyright ownership. The
> +# ASF licenses this file to you under the Apache License, Version 2.0 (the
> +# "License"); you may not use this file except in compliance with the
> +# License. You may obtain a copy of the License at
> +#
> +# http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
> +# License for the specific language governing permissions and limitations
> +# under the License.
> +
> +class FirewallRule < BaseModel
> + attr_accessor :allow_protocol # tcp/udp/icmp
> + attr_accessor :port_from
> + attr_accessor :port_to
> + attr_accessor :sources
> + attr_accessor :direction #ingress egress
> +end
> diff --git a/server/public/javascripts/application.js b/server/public/javascripts/application.js
> index 95c9bc2..703879c 100644
> --- a/server/public/javascripts/application.js
> +++ b/server/public/javascripts/application.js
> @@ -19,10 +19,10 @@ $(document).ready(function() {
>
> function more_fields()
> {
> - //increment the hidden input that captures how many meta_data are passed
> - var meta_params = document.getElementsByName('meta_params')
> + //increment the hidden input that captures how many meta_data are passed
> + var meta_params = document.getElementsByName('meta_params')
> current_number_params = eval(meta_params[0].value)+1
> - meta_params[0].value = current_number_params
> + meta_params[0].value = current_number_params
> var new_meta = document.getElementById('metadata_holder').cloneNode(true);
> new_meta.id = 'metadata_holder' + current_number_params;
> new_meta.style.display = 'block';
> @@ -39,15 +39,50 @@ function more_fields()
> function less_fields()
> {
> var meta_params = document.getElementsByName('meta_params')
> - current_val = eval(meta_params[0].value)
> - if (current_val == 0)
> - {
> - return;
> - }
> - else
> - {
> - var theDiv = document.getElementById('metadata_holder'+current_val)
> - theDiv.parentNode.removeChild(theDiv)
> - meta_params[0].value = eval(current_val)-1
> - }
> + current_val = eval(meta_params[0].value)
> + if (current_val == 0)
> + {
> + return;
> + }
> + else
> + {
> + var theDiv = document.getElementById('metadata_holder'+current_val)
> + theDiv.parentNode.removeChild(theDiv)
> + meta_params[0].value = eval(current_val)-1
> + }
> +}
> +
> +var addresses = 0;
> +var groups = 0;
> +function make_fields(type)
> +{
> + form = document.getElementById("new_rule_form")
> + button = document.getElementById("submit_button")
> + if(type == "address")
> + {
> + name = "ip_address" + eval(++addresses)
> + create_rule_source_field(name, "Address " + eval(addresses) + " [use CIDR notation 0.0.0.0/0]", form, button)
> + }
> + else if(type == "group")
> + {
> + name = "group" + eval(++groups)
> + create_rule_source_field(name, "Name of group " + eval(groups), form, button)
> + name = "group" + eval(groups) + "owner"
> + create_rule_source_field(name, "Group " + eval(groups) + " owner (required)", form, button)
> + }
> +}
> +
> +function create_rule_source_field(name, label, form, button)
> +{
> + element = document.createElement("INPUT")
> + element.type = "input"
> + element.size = 35
> + element.name = name
> + text = document.createTextNode(label)
> + form.insertBefore(element, button)
> + form.insertBefore(text, element)
> + form.insertBefore(document.createElement('BR'), element)
> + form.insertBefore(document.createElement('BR'), button)
> + form.insertBefore(document.createElement('BR'), button)
> + form.insertBefore(document.createElement('BR'), button)
> }
> diff --git a/server/server.rb b/server/server.rb
> index ba87c67..ae23263 100644
> --- a/server/server.rb
> +++ b/server/server.rb
> @@ -948,3 +948,115 @@ collection :addresses do
> end
>
> end
> +
> +#html for creating a new firewall
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/firewalls/new" do
> + respond_to do |format|
> + format.html { haml :"firewalls/new" }
> + end
> +end
> +
> +#html for creating a new firewall rule
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/firewalls/:firewall/new_rule" do
> + @firewall_name = params[:firewall]
> + respond_to do |format|
> + format.html {haml :"firewalls/new_rule" }
> + end
> +end
> +
> +#FIREWALLS
> +collection :firewalls do
> + description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
> + operation :index do
> + description 'List all firewalls'
> + with_capability :firewalls
> + control { filter_all(:firewalls) }
> + end
> +
> + operation :show do
> + description 'Show details for a specific firewall - list all rules'
> + with_capability :firewall
> + param :id, :string, :required
> + control { show(:firewall) }
> + end
> +
> + operation :create do
> + description 'Create a new firewall'
> + with_capability :create_firewall
> + param :name, :string, :required
> + param :description, :string, :required
> + control do
> + @firewall = driver.create_firewall(credentials, params )
> + respond_to do |format|
> + format.xml do
> + response.status = 201 # Created
> + haml :"firewalls/show"
> + end
> + format.html {haml :"firewalls/show"}
> + format.json {convert_to_json(:firewall, @firewall)}
> + end
> + end
> + end
> +
> + operation :destroy do
> + description 'Delete a specified firewall - error if firewall has rules'
> + with_capability :delete_firewall
> + param :id, :string, :required
> + control do
> + driver.delete_firewall(credentials, params)
> + respond_to do |format|
> + format.xml { 204 }
> + format.json { 204 }
> + format.html { redirect(firewalls_url) }
> + end
> + end
> + end
> +
> +#create a new firewall rule - POST /api/firewalls/:firewall/rules
> + operation :rules, :method => :post, :member => true do
> + description 'Create a new firewall rule for the specified firewall'
> + param :firewall, :required, :string, [], "Name of firewall in which to apply this rule"
> + param :protocol, :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
> + param :from_port, :required, :string, [], "Start of port range for the rule"
> + param :to_port, :required, :string, [], "End of port range for the rule"
> + with_capability :create_firewall_rule
> + control do
> + #source IPs from params
> + addresses = params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
> + #source groups from params
> + groups = {}
> + max_groups = params.select{|k,v| k=~/^group/}.size/2
> + for i in (1..max_groups) do
> + groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
> + end
> + params.merge!( {'addresses' => addresses} ) ; params.merge!( {'groups' => groups} )
> + driver.create_firewall_rule(credentials, params)
> + @firewall = driver.firewall(credentials, {:id => params[:firewall]})
> + respond_to do |format|
> + format.html {haml :"firewalls/show"}
> + format.xml do
> + response.status = 201 #created
> + haml :"firewall/show"
> + end
> + format.json {convert_to_json(:firewall, @firewall)}
> + end
> + end
> + end
> +
> +#delete a firewall rule DELETE /api/firewalls/:firewall/rule - with param rule_id
> + operation :rule, :method => :delete, :member => true do
> + description 'Delete the specified firewall rule from the given firewall'
> + param :firewall, :required, :string
> + param :rule_id, :required, :string
> + with_capability :delete_firewall_rule
> + control do
> + driver.delete_firewall_rule(credentials, params)
> + respond_to do |format|
> + format.html {redirect firewall_url(params[:id])}
> + format.xml {204}
> + format.json {204}
> + end
> + end
> + end
> +
> +end #firewalls
> diff --git a/server/views/firewalls/index.html.haml b/server/views/firewalls/index.html.haml
> new file mode 100644
> index 0000000..3312a32
> --- /dev/null
> +++ b/server/views/firewalls/index.html.haml
> @@ -0,0 +1,25 @@
> +%h1 Firewalls
> +%br
> +%p
> + =link_to 'Create new firewall', "/api/firewalls/new"
> +%table.display
> + %thead
> + %tr
> + %th Id
> + %th Name
> + %th Description
> + %th Owner ID
> + %th Rules
> + %tbody
> + - @firewalls.each do |firewall|
> + %tr
> + %td
> + = link_to firewall.id, firewall_url(firewall.id)
> + %td
> + = firewall.name
> + %td
> + = firewall.description
> + %td
> + = firewall.owner_id
> + %td
> + = link_to 'view rules', firewall_url(firewall.id)
> diff --git a/server/views/firewalls/index.xml.haml b/server/views/firewalls/index.xml.haml
> new file mode 100644
> index 0000000..f027785
> --- /dev/null
> +++ b/server/views/firewalls/index.xml.haml
> @@ -0,0 +1,23 @@
> +!!! XML
> +%firewalls
> + - @firewalls.each do |firewall|
> + %firewall{:href => firewall_url(firewall.id), :id => firewall.id}
> + - firewall.attributes.select{ |attr| attr != :id && attr!= :rules}.each do |attribute|
> + - haml_tag("#{attribute}".tr('-', '_'), :<) do
> + - if [:name, :description].include?(attribute)
> + =cdata do
> + - haml_concat firewall.send(attribute)
> + - else
> + - haml_concat firewall.send(attribute)
> + %rules
> + - firewall.rules.each do |rule|
> + %rule{:id => rule.id}
> + - rule.attributes.select{|attr| attr != :sources && attr != :id}.each do |rule_attrib|
> + - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do
> + - haml_concat rule.send(rule_attrib)
> + %sources
> + - rule.sources.each do |source|
> + - if source[:type] == "group"
> + %source{:name => source[:name], :type=> source[:type], :owner=> source[:owner]}
> + - else
> + %source{:prefix => source[:prefix], :address=> source[:address], :family=>source[:family], :type => source[:type]}
> \ No newline at end of file
> diff --git a/server/views/firewalls/new.html.haml b/server/views/firewalls/new.html.haml
> new file mode 100644
> index 0000000..4a230a6
> --- /dev/null
> +++ b/server/views/firewalls/new.html.haml
> @@ -0,0 +1,11 @@
> +%h1 New Firewall
> +
> +%form{:action => firewalls_url, :method => :post}
> + %label
> + Firewall Name
> + %input{:name => 'name', :size => 25}/
> + %br
> + %label
> + Firewall Description
> + %input{:name => 'description', :size => 100}/
> + %input{:type => :submit, :name => "commit", :value=>"create"}
> \ No newline at end of file
> diff --git a/server/views/firewalls/new_rule.html.haml b/server/views/firewalls/new_rule.html.haml
> new file mode 100644
> index 0000000..b25206a
> --- /dev/null
> +++ b/server/views/firewalls/new_rule.html.haml
> @@ -0,0 +1,26 @@
> +%h1 New Firewall Rule
> +
> +%form{ :action => "#{firewall_url(@firewall_name)}/rules", :id => "new_rule_form", :method => :post, :enctype => 'multipart/form-data'}
> + %label
> + Protocol:
> + %br
> + %input{ :name => 'protocol', :size => 10}/
> + %br
> + %br
> + %label
> + From port:
> + %br
> + %input{ :name => 'from_port', :size => 10}/
> + %br
> + %br
> + To port:
> + %br
> + %input{ :name => 'to_port', :size => 10}/
> + %br
> + %br
> + %a{ :href => "javascript:;", :onclick => "make_fields('address');"} Add source IP address
> + %br
> + %a{ :href => "javascript:;", :onclick => "make_fields('group');"} Add source group
> + %br
> + %br
> + %input{ :type => :submit, :id => "submit_button", :name => "commit", :value => "create"}/
> diff --git a/server/views/firewalls/show.html.haml b/server/views/firewalls/show.html.haml
> new file mode 100644
> index 0000000..b77aaa4
> --- /dev/null
> +++ b/server/views/firewalls/show.html.haml
> @@ -0,0 +1,44 @@
> +%h1 Firewall
> +%h2
> + = @firewall.id
> +%dl
> + %di
> + %dt Name
> + %dd
> + = @firewall.name
> + %dt Owner
> + %dd
> + = @firewall.owner_id
> + %dt Description
> + %dd
> + = @firewall.description
> +
> +%h2
> + Rules
> + %br
> + %p
> + =link_to 'Create a new rule', "/api/firewalls/#{@firewall.name}/new_rule"
> +%dl
> + - @firewall.rules.each do |rule|
> + %di
> + Rule
> + - rule.attributes.select{|attr| attr != :sources}.each do |attrib|
> + %dt #{attrib}
> + %dd
> + = rule.send(attrib)
> + %dt sources
> + %dd
> + - rule.sources.each do |source|
> + - if source[:type] == "group"
> + type: #{source[:type]}, name: #{source[:name]}, owner: #{source[:owner]}
> + %br
> + - else
> + type: #{source[:type]}, family: #{source[:family]}, address: #{source[:address]}, prefix: #{source[:prefix]}
> + %br
> + %dd
> + %form{ :action => "#{firewall_url(@firewall.name)}/rule", :method => :post}
> + %input{:type => "hidden", :name => "_method", :value => "delete"}
> + %input{:type => "hidden", :name => "rule_id", :value => rule.id}
> + %input{:type => :submit, :value => "Delete Rule"}
> + %dd
> + = link_to_action 'Delete Firewall', destroy_firewall_url(@firewall.name), :delete
> diff --git a/server/views/firewalls/show.xml.haml b/server/views/firewalls/show.xml.haml
> new file mode 100644
> index 0000000..9d1fc48
> --- /dev/null
> +++ b/server/views/firewalls/show.xml.haml
> @@ -0,0 +1,21 @@
> +!!! XML
> +%firewall{:href => firewall_url(@firewall.id), :id => @firewall.id}
> + - @firewall.attributes.select{ |attr| attr != :id && attr!= :rules}.each do |attribute|
> + - haml_tag("#{attribute}".tr('-', '_'), :<) do
> + - if [:name, :description].include?(attribute)
> + =cdata do
> + - haml_concat @firewall.send(attribute)
> + - else
> + - haml_concat @firewall.send(attribute)
> + %rules
> + - @firewall.rules.each do |rule|
> + %rule{:id => rule.id}
> + - rule.attributes.select{|attr| attr != :sources && attr != :id}.each do |rule_attrib|
> + - haml_tag("#{rule_attrib}".tr('-', '_'), :<) do
> + - haml_concat rule.send(rule_attrib)
> + %sources
> + - rule.sources.each do |source|
> + - if source[:type] == "group"
> + %source{:name => source[:name], :type=> source[:type], :owner=>source[:owner]}
> + - else
> + %source{:prefix => source[:prefix], :address=> source[:address], :family=>source[:family], :type => source[:type]}
> \ No newline at end of file
> --
> 1.7.3.4
>
------------------------------------------------------
Michal Fojtik, mfojtik@redhat.com
Deltacloud API: http://deltacloud.org