cloudflare 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/Gemfile +0 -2
- data/README.md +28 -1
- data/lib/cloudflare/connection.rb +18 -0
- data/lib/cloudflare/version.rb +1 -1
- data/lib/cloudflare/zone.rb +83 -4
- data/spec/cloudflare/zone_spec.rb +65 -14
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7803b3a770a2ca6cfe874d77a7172bce3b0a3016
|
4
|
+
data.tar.gz: 8e97d03f70b94c9c6e5534adeff3fd9258c6a56c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df0801c3eaeca54ebdf36c45eecb85ae27f39eeae1163474ace6fda7211357aae6c9ddefee4f4fa12a45a34d99509011965e9d2af4d9e4139f75dbb7ee68c6d4
|
7
|
+
data.tar.gz: bb7ee1e783f5288612252a2908ef7e1d8b27daa2ba5c96947b09faf35fb6b536c91512d0fda099c6cac3a453ec8db9a8211fa5fcf12069b9a82c382e57b4c562
|
data/.gitignore
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -66,6 +66,29 @@ puts records.first.record[:name]
|
|
66
66
|
puts records
|
67
67
|
```
|
68
68
|
|
69
|
+
Get firewall rules:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
all_rules = zones.first.firewall_rules.all
|
73
|
+
block_rules = zones.first.firewall_rules.all("block") # or "whitelist" or "challenge"
|
74
|
+
```
|
75
|
+
|
76
|
+
Get blocked ips:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
block_rules = zones.first.firewall_rules.all("block")
|
80
|
+
blocked_ips = zones.first.firewall_rules.firewalled_ips(block_rules)
|
81
|
+
```
|
82
|
+
|
83
|
+
Block an ip:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
# ip = "nnn.nnn.nnn.nnn"
|
87
|
+
# note: "some note about the block"
|
88
|
+
data = {"mode":"block","configuration":{"target":"ip","value":"#{ip}"},"notes":"#{note} #{Time.now.strftime("%m/%d/%y")} "}
|
89
|
+
response = zones.first.firewall_rules.post(data.to_json, content_type: 'application/json')
|
90
|
+
```
|
91
|
+
|
69
92
|
## Contributing
|
70
93
|
|
71
94
|
1. Fork it
|
@@ -84,7 +107,8 @@ puts records
|
|
84
107
|
Released under the MIT license.
|
85
108
|
|
86
109
|
Copyright, 2012, 2014, by [Marcin Prokop](https://github.com/b4k3r).
|
87
|
-
Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
|
110
|
+
Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
|
111
|
+
Copyright, 2017, by [David Rosenbloom](http://artifactory.com).
|
88
112
|
|
89
113
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
90
114
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -103,3 +127,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
103
127
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
104
128
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
105
129
|
THE SOFTWARE.
|
130
|
+
|
131
|
+
|
132
|
+
|
@@ -31,6 +31,8 @@ module Cloudflare
|
|
31
31
|
TIMEOUT = 10 # Default is 5 seconds
|
32
32
|
|
33
33
|
class Resource < RestClient::Resource
|
34
|
+
include Enumerable
|
35
|
+
|
34
36
|
# @param api_key [String] `X-Auth-Key` or `X-Auth-User-Service-Key` if no email provided.
|
35
37
|
# @param email [String] `X-Auth-Email`, your email address for the account.
|
36
38
|
def initialize(url = DEFAULT_URL, key: nil, email: nil, **options)
|
@@ -48,6 +50,22 @@ module Cloudflare
|
|
48
50
|
Response.new(response.request.url, response.body)
|
49
51
|
end
|
50
52
|
end
|
53
|
+
|
54
|
+
def paginate(obj, url, url_args = "")
|
55
|
+
page = 1
|
56
|
+
page_size = 100
|
57
|
+
results = []
|
58
|
+
|
59
|
+
# fetch and aggregate all pages
|
60
|
+
loop do
|
61
|
+
rules = obj.new(concat_urls(url, "?scope_type=organization#{url_args}&per_page=#{page_size}&page=#{page}"), self, **options)
|
62
|
+
results += rules.get.results
|
63
|
+
break if results.size % page_size != 0
|
64
|
+
page += 1
|
65
|
+
end
|
66
|
+
|
67
|
+
return results
|
68
|
+
end
|
51
69
|
end
|
52
70
|
|
53
71
|
class Connection < Resource
|
data/lib/cloudflare/version.rb
CHANGED
data/lib/cloudflare/zone.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright, 2012, by Marcin Prokop.
|
2
2
|
# Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
3
|
+
# Copyright, 2017, by David Rosenbloom. <http://artifactory.com>
|
3
4
|
#
|
4
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
6
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -34,7 +35,12 @@ module Cloudflare
|
|
34
35
|
|
35
36
|
@record = record || self.get.result
|
36
37
|
end
|
37
|
-
|
38
|
+
|
39
|
+
def update_content(content)
|
40
|
+
response = self.put({type: @record[:type], name: @record[:name], content: content}.to_json, content_type: 'application/json')
|
41
|
+
response.successful?
|
42
|
+
end
|
43
|
+
|
38
44
|
attr :record
|
39
45
|
|
40
46
|
def to_s
|
@@ -52,7 +58,8 @@ module Cloudflare
|
|
52
58
|
attr :zone
|
53
59
|
|
54
60
|
def all
|
55
|
-
|
61
|
+
results = paginate(DNSRecords, url)
|
62
|
+
results.map{|record| DNSRecord.new(concat_urls(url, record[:id]), record, **options)}
|
56
63
|
end
|
57
64
|
|
58
65
|
def find_by_name(name)
|
@@ -70,10 +77,78 @@ module Cloudflare
|
|
70
77
|
end
|
71
78
|
end
|
72
79
|
|
73
|
-
class
|
80
|
+
class FirewallRule < Resource
|
74
81
|
def initialize(url, record = nil, **options)
|
75
82
|
super(url, **options)
|
83
|
+
|
84
|
+
@record = record || self.get.result
|
85
|
+
end
|
86
|
+
|
87
|
+
attr :record
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
"#{@record[:configuration][:value]} - #{@record[:mode]} - #{@record[:notes]}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class FirewallRules < Resource
|
95
|
+
def initialize(url, zone, **options)
|
96
|
+
super(url, **options)
|
97
|
+
|
98
|
+
@zone = zone
|
99
|
+
end
|
100
|
+
|
101
|
+
attr :zone
|
102
|
+
|
103
|
+
def all(mode = nil, ip = nil, notes = nil)
|
104
|
+
url_args = ""
|
105
|
+
url_args.concat("&mode=#{mode}") if mode
|
106
|
+
url_args.concat("&configuration_value=#{ip}") if ip
|
107
|
+
url_args.concat("¬es=#{notes}") if notes
|
108
|
+
|
109
|
+
results = paginate(FirewallRules, url, url_args)
|
110
|
+
results.map{|record| FirewallRule.new(concat_urls(url, record[:id]), record, **options)}
|
111
|
+
end
|
112
|
+
|
113
|
+
def firewalled_ips(rules)
|
114
|
+
rules.collect {|r| r.record[:configuration][:value]}
|
115
|
+
end
|
116
|
+
|
117
|
+
def blocked_ips
|
118
|
+
firewalled_ips(all("block"))
|
119
|
+
end
|
120
|
+
|
121
|
+
def set(mode, ip, note)
|
122
|
+
data = {
|
123
|
+
mode: mode.to_s,
|
124
|
+
configuration: {
|
125
|
+
target: "ip",
|
126
|
+
value: ip.to_s,
|
127
|
+
notes: "cloudflare gem firewall_rules [#{mode}] #{note} #{Time.now.strftime("%m/%d/%y")}"
|
128
|
+
}
|
129
|
+
}
|
76
130
|
|
131
|
+
post(data.to_json, content_type: 'application/json')
|
132
|
+
end
|
133
|
+
|
134
|
+
def unset(mode, value)
|
135
|
+
rule = send("find_by_#{mode}", value)
|
136
|
+
rule.delete
|
137
|
+
end
|
138
|
+
|
139
|
+
def find_by_id(id)
|
140
|
+
FirewallRule.new(concat_urls(url, id), **options)
|
141
|
+
end
|
142
|
+
|
143
|
+
def find_by_ip(ip)
|
144
|
+
rule = FirewallRule.new(concat_urls(url, "?configuration_value=#{ip}"), **options)
|
145
|
+
FirewallRule.new(concat_urls(url, rule.record.first[:id]), **options)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class Zone < Resource
|
150
|
+
def initialize(url, record = nil, **options)
|
151
|
+
super(url, **options)
|
77
152
|
@record = record || self.get.result
|
78
153
|
end
|
79
154
|
|
@@ -83,6 +158,10 @@ module Cloudflare
|
|
83
158
|
@dns_records ||= DNSRecords.new(concat_urls(url, 'dns_records'), self, **options)
|
84
159
|
end
|
85
160
|
|
161
|
+
def firewall_rules
|
162
|
+
@firewall_rules ||= FirewallRules.new(concat_urls(url, "firewall/access_rules/rules"), self, **options)
|
163
|
+
end
|
164
|
+
|
86
165
|
def to_s
|
87
166
|
@record[:name]
|
88
167
|
end
|
@@ -94,7 +173,7 @@ module Cloudflare
|
|
94
173
|
end
|
95
174
|
|
96
175
|
def find_by_name(name)
|
97
|
-
|
176
|
+
response = self.get(params: {name: name})
|
98
177
|
|
99
178
|
unless response.empty?
|
100
179
|
record = response.results.first
|
@@ -1,41 +1,92 @@
|
|
1
1
|
|
2
2
|
RSpec.describe "Cloudflare DNS Zones" do
|
3
3
|
include_context Cloudflare::RSpec::Connection
|
4
|
-
|
4
|
+
|
5
5
|
it "should list zones" do
|
6
6
|
zones = connection.zones.all
|
7
|
-
|
7
|
+
|
8
8
|
expect(zones).to be_any
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
describe Cloudflare::DNSRecords, order: :defined do
|
12
12
|
let(:zone) {connection.zones.all.first}
|
13
|
+
|
13
14
|
let(:name) {"test"}
|
14
|
-
|
15
|
+
let(:ip) {"123.123.123.123"}
|
16
|
+
record = nil
|
17
|
+
|
18
|
+
it "should get all records" do
|
19
|
+
result = zone.dns_records.all
|
20
|
+
|
21
|
+
puts "===> #{result.size} records returned"
|
22
|
+
expect(result.size).to be > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
|
15
26
|
it "should create dns record" do
|
16
27
|
response = zone.dns_records.post({
|
17
28
|
type: "A",
|
18
29
|
name: name,
|
19
|
-
content:
|
30
|
+
content: ip,
|
20
31
|
ttl: 240,
|
21
32
|
proxied: false
|
22
33
|
}.to_json, content_type: 'application/json')
|
23
|
-
|
34
|
+
|
24
35
|
expect(response).to be_successful
|
25
|
-
|
36
|
+
|
26
37
|
result = response.result
|
27
38
|
expect(result).to include(:id, :type, :name, :content, :ttl)
|
39
|
+
record = result
|
28
40
|
end
|
29
|
-
|
41
|
+
|
30
42
|
it "should delete dns record" do
|
31
|
-
|
32
|
-
|
33
|
-
expect(
|
34
|
-
|
35
|
-
|
36
|
-
|
43
|
+
dns_record = zone.dns_records.find_by_id(record[:id])
|
44
|
+
response = dns_record.delete
|
45
|
+
expect(response).to be_successful
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe Cloudflare::FirewallRules, order: :defined do
|
50
|
+
let(:zone) {connection.zones.all.first}
|
51
|
+
let(:name) {"test"}
|
52
|
+
let(:ip) {'123.123.123.123'}
|
53
|
+
let(:ip2) {'123.123.123.124'}
|
54
|
+
let(:notes) {"gemtest"}
|
55
|
+
record = nil
|
56
|
+
before do
|
57
|
+
response = zone.firewall_rules.set('block', ip2, notes)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get all rules" do
|
61
|
+
result = zone.firewall_rules.all
|
62
|
+
|
63
|
+
puts "===> #{result.size} records returned"
|
64
|
+
expect(result.size).to be > 0
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should create firewall rules for 'block', 'challenge', 'whitelist'" do
|
68
|
+
|
69
|
+
[:block, :challenge, :whitelist].each do |mode|
|
70
|
+
response = zone.firewall_rules.set(mode, ip, notes)
|
37
71
|
expect(response).to be_successful
|
72
|
+
|
73
|
+
result = response.result
|
74
|
+
expect(result).to include(:id, :mode, :notes, :configuration)
|
75
|
+
expect(result[:mode]).to eq mode.to_s
|
76
|
+
record = result
|
38
77
|
end
|
39
78
|
end
|
79
|
+
|
80
|
+
it "should delete firewall rule by record" do
|
81
|
+
response = zone.firewall_rules.unset('id', record[:id])
|
82
|
+
|
83
|
+
expect(response).to be_successful
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should delete firewall rule by ip" do
|
87
|
+
response = zone.firewall_rules.unset('ip', ip2)
|
88
|
+
|
89
|
+
expect(response).to be_successful
|
90
|
+
end
|
40
91
|
end
|
41
92
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudflare
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcin Prokop
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|
@@ -75,6 +75,7 @@ executables: []
|
|
75
75
|
extensions: []
|
76
76
|
extra_rdoc_files: []
|
77
77
|
files:
|
78
|
+
- ".gitignore"
|
78
79
|
- ".rspec"
|
79
80
|
- ".travis.yml"
|
80
81
|
- Gemfile
|
@@ -110,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
111
|
version: '0'
|
111
112
|
requirements: []
|
112
113
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.6.
|
114
|
+
rubygems_version: 2.6.12
|
114
115
|
signing_key:
|
115
116
|
specification_version: 4
|
116
117
|
summary: A Ruby wrapper for the Cloudflare API.
|