Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
168e52f
Initial WAFRules. Tabs replaced.
artifactory Jul 24, 2017
54250d4
WIP: begin to page WAF results.
artifactory Jul 24, 2017
18d9c67
Added paging for WAFRules.
artifactory Jul 25, 2017
2cabecb
Updated WAF to Firewall, _rules to _blocks for greater naming accuracy.
artifactory Jul 25, 2017
340f773
Genericized firewall_blocks to firewall_rules(mode); added firewalled…
artifactory Jul 25, 2017
687283a
fix find_by_name for zones
sonicdes Jul 25, 2017
e026134
Merge pull request #22 from sonicdes/master
ioquatix Jul 26, 2017
005274d
Fixed firewall_rules; filtered search on mode, ip.
artifactory Jul 27, 2017
59f6c34
Bumped version.
artifactory Jul 27, 2017
79930c8
Modified firewalled_ips.
artifactory Jul 27, 2017
5455303
Added resource access for firewall rules to allow for posts etc. TODO…
artifactory Jul 27, 2017
349645c
Make class more consistent wih existing; update readme.
artifactory Jul 27, 2017
1f9e688
Update cloudflare.gemspec
artifactory Jul 28, 2017
cd67fd9
Update zone.rb
artifactory Jul 28, 2017
7ffa245
Restored tabs.
artifactory Jul 28, 2017
ddf9eee
Merge branch 'ip_block' of https://github.com/artifactory/cloudflare …
artifactory Jul 28, 2017
cde31bd
Merge branch 'master' into ip_block
artifactory Jul 28, 2017
abf7d77
Update README.md
artifactory Jul 28, 2017
1fadef7
Update zone.rb
artifactory Jul 28, 2017
975bb05
update record content
molizz Jul 28, 2017
dc6d4d6
Update zone.rb
artifactory Jul 28, 2017
c166140
Merge pull request #25 from molisoft/master
ioquatix Jul 29, 2017
ea557ad
Restored original connection.rb to minimize PR whitespace annoyance.
artifactory Jul 31, 2017
0981aaa
Merge branch 'ip_block' of https://github.com/artifactory/cloudflare …
artifactory Jul 31, 2017
950f1f6
Replaced regex check of ip with IPAddr.ipv4?
artifactory Jul 31, 2017
8c7ee98
WIP: firewall_rules spec.
artifactory Jul 31, 2017
dc29f6f
--amend
artifactory Jul 31, 2017
2b3fbed
WIP:
artifactory Jul 31, 2017
5a25ec7
--amend
artifactory Jul 31, 2017
fbd92de
Fixed bug introduced to firewall_rules.all by previous change; added …
artifactory Aug 1, 2017
fb1d935
Deleted commented line.
artifactory Aug 1, 2017
0b74c7b
Whitespace conversion.
artifactory Aug 1, 2017
bf4f480
Merge branch 'master' into ip_block
artifactory Aug 1, 2017
7b30886
Bumped minor rev #.
artifactory Aug 1, 2017
eecbbde
Merge branch 'ip_block' of https://github.com/artifactory/cloudflare …
artifactory Aug 1, 2017
168ebed
Extract pagination.
artifactory Aug 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
t/
Gemfile*
*.gem
tags
.byebug_history
.rspec_status
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,29 @@ puts records.first.record[:name]
puts records
```

Get firewall rules:

``` ruby
all_rules = zones.first.firewall_rules.all
block_rules = zones.first.firewall_rules.all("block") # or "whitelist" or "challenge"
```

Get blocked ips:

``` ruby
block_rules = zones.first.firewall_rules.all("block")
blocked_ips = zones.first.firewall_rules.firewalled_ips(block_rules)
```

Block an ip:

``` ruby
# ip = "nnn.nnn.nnn.nnn"
# note: "some note about the block"
data = {"mode":"block","configuration":{"target":"ip","value":"#{ip}"},"notes":"#{note} #{Time.now.strftime("%m/%d/%y")} "}
response = zones.first.firewall_rules.post(data.to_json, content_type: 'application/json')

```
## Contributing

1. Fork it
Expand All @@ -83,7 +106,7 @@ puts records

Released under the MIT license.

Copyright, 2012, 2014, by [Marcin Prokop](https://github.com/b4k3r).
Copyright, 2012, 2014, by [Marcin Prokop](https://github.com/b4k3r).
Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand All @@ -103,3 +126,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



25 changes: 21 additions & 4 deletions lib/cloudflare/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,44 @@
module Cloudflare
DEFAULT_URL = "https://api.cloudflare.com/client/v4/"
TIMEOUT = 10 # Default is 5 seconds

class Resource < RestClient::Resource
include Enumerable
# @param api_key [String] `X-Auth-Key` or `X-Auth-User-Service-Key` if no email provided.
# @param email [String] `X-Auth-Email`, your email address for the account.
def initialize(url = DEFAULT_URL, key: nil, email: nil, **options)
headers = options[:headers] || {}

if email.nil?
headers['X-Auth-User-Service-Key'] = key
else
headers['X-Auth-Key'] = key
headers['X-Auth-Email'] = email
end

# Convert HTTP API responses to our own internal response class:
super(url, headers: headers, accept: 'application/json', **options) do |response|
Response.new(response.request.url, response.body)
end
end

def paginate(obj, url, url_args = "")
page = 1
page_size = 100
results = []

loop do # fetch and aggregate all pages
rules = obj.new(concat_urls(url, "?scope_type=organization#{url_args}&per_page=#{page_size}&page=#{page}"), self, **options)
results += rules.get.results
break if results.size % page_size != 0
page += 1
end
results
end



end

class Connection < Resource
end
end
2 changes: 1 addition & 1 deletion lib/cloudflare/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
# THE SOFTWARE.

module Cloudflare
VERSION = '3.0.0'
VERSION = '3.1.3'
end
121 changes: 97 additions & 24 deletions lib/cloudflare/zone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# added firewall rules support: david rosenbloom|davidr@artifactory.com|artifactory
#
require_relative 'connection'

module Cloudflare
Expand All @@ -27,82 +29,153 @@ def zones
@zones ||= Zones.new(concat_urls(url, 'zones'), options)
end
end

class DNSRecord < Resource
def initialize(url, record = nil, **options)
super(url, **options)

@record = record || self.get.result
end



def update_content(content)
response = self.put({type: @record[:type], name: @record[:name], content: content}.to_json, content_type: 'application/json')
response.successful?
end

attr :record

def to_s
"#{@record[:name]} #{@record[:type]} #{@record[:content]}"
end
end

class DNSRecords < Resource
def initialize(url, zone, **options)
super(url, **options)

@zone = zone
end

attr :zone

def all
self.get.results.map{|record| DNSRecord.new(concat_urls(url, record[:id]), record, **options)}
results = paginate(DNSRecords, url)
results.map{|record| DNSRecord.new(concat_urls(url, record[:id]), record, **options)}
end

def find_by_name(name)
response = self.get(params: {name: name})

unless response.empty?
record = response.results.first

DNSRecord.new(concat_urls(url, record[:id]), record, **options)
end
end

def find_by_id(id)
DNSRecord.new(concat_urls(url, id), **options)
end
end


class FirewallRule < Resource
def initialize(url, record = nil, **options)
super(url, **options)

@record = record || self.get.result
end

attr :record

def to_s
"#{@record[:configuration][:value]} - #{@record[:mode]} - #{@record[:notes]}"
end
end

class FirewallRules < Resource
def initialize(url, zone, **options)
super(url, **options)

@zone = zone
end

attr :zone

def all(mode = nil, ip = nil, notes = nil)
url_args = ""
url_args.concat("&mode=#{mode}") if mode
url_args.concat("&configuration_value=#{ip}") if ip
url_args.concat("&notes=#{notes}") if notes

results = paginate(FirewallRules, url, url_args)
results.map{|record| FirewallRule.new(concat_urls(url, record[:id]), record, **options)}
end

def firewalled_ips(rules)
rules.collect {|r| r.record[:configuration][:value]}
end

def blocked_ips
firewalled_ips(all("block"))
end

def set(mode, ip, note)
data = {"mode":"#{mode.to_s}","configuration":{"target":"ip","value":"#{ip}"},"notes":"cloudflare gem firewall_rules [#{mode}] #{note} #{Time.now.strftime("%m/%d/%y")} "}
post(data.to_json, content_type: 'application/json')
end

def unset(mode, value)
rule = send("find_by_#{mode}", value)
rule.delete
end

def find_by_id(id)
FirewallRule.new(concat_urls(url, id), **options)
end

def find_by_ip(ip)
rule = FirewallRule.new(concat_urls(url, "?configuration_value=#{ip}"), **options)
FirewallRule.new(concat_urls(url, rule.record.first[:id]), **options)
end
end

class Zone < Resource
def initialize(url, record = nil, **options)
super(url, **options)

@record = record || self.get.result
end

attr :record

def dns_records
@dns_records ||= DNSRecords.new(concat_urls(url, 'dns_records'), self, **options)
end


def firewall_rules
@firewall_rules ||= FirewallRules.new(concat_urls(url, "firewall/access_rules/rules"), self, **options)
end

def to_s
@record[:name]
end
end

class Zones < Resource
def all
self.get.results.map{|record| Zone.new(concat_urls(url, record[:id]), record, **options)}
end

def find_by_name(name)
record = self.get(params: {name: name}).result
response = self.get(params: {name: name})

unless response.empty?
record = response.results.first

Zone.new(concat_urls(url, record[:id]), record, **options)
end
end

def find_by_id(id)
Zone.new(concat_urls(url, id), **options)
end
Expand Down
Loading