Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ gem 'statsd-ruby'
gem 'activemodel', '~> 4.2.5.2'
gem 'actionpack', '~> 4.2.5.2'
gem 'actionview', '~> 4.2.5.2'
gem 'public_suffix'

# We need to use https for git urls as the git protocol is blocked by various
# firewalls
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ GEM
pry-byebug (3.1.0)
byebug (~> 4.0)
pry (~> 0.10)
public_suffix (1.5.3)
rack (1.6.4)
rack-protection (1.5.3)
rack
Expand Down Expand Up @@ -416,6 +417,7 @@ DEPENDENCIES
parallel_tests
pg (= 0.16.0)
pry-byebug
public_suffix
rack-test
railties (~> 4.2.5.2)
rake
Expand Down
23 changes: 23 additions & 0 deletions app/models/runtime/private_domain.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'models/runtime/domain'
require 'public_suffix'

module VCAP::CloudController
class PrivateDomain < Domain
Expand Down Expand Up @@ -39,6 +40,8 @@ def as_summary_json

def validate
super
errors.add(:name, :reserved) if reserved?

validates_presence :owning_organization
exclude_domains_from_same_org = Domain.dataset.
exclude(owning_organization_id: owning_organization_id).
Expand Down Expand Up @@ -70,6 +73,21 @@ def shared?
false
end

class << self
def configure(filename)
list = nil
if filename
File.open(filename) do |f|
list = PublicSuffix::List.parse(f)
end
else
list = PublicSuffix::List.new
end

PublicSuffix::List.default = list
end
end

private

def shared_by?(org)
Expand All @@ -84,5 +102,10 @@ def validate_total_private_domains
errors.add(:organization, :total_private_domains_exceeded)
end
end

def reserved?
rule = PublicSuffix::List.default.find(name)
!rule.nil? && !rule.allow?(name)
end
end
end
3 changes: 3 additions & 0 deletions bosh-templates/cloud_controller_api.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ external_domain: <%= p("cc.external_host") %>.<%= p("domain") %>
system_domain_organization: <%= p("system_domain_organization") %>
system_domain: <%= p("system_domain") %>
app_domains: [ <%= p("app_domains").join(", ") %> ]
<% if_p("cc.reserved_private_domains") do |reserved| %>
reserved_private_domains: <%= reserved %>
<% end %>

jobs:
global:
Expand Down
3 changes: 3 additions & 0 deletions bosh-templates/cloud_controller_clock.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ external_domain: <%= p("cc.external_host") %>.<%= p("domain") %>
system_domain_organization: <%= p("system_domain_organization") %>
system_domain: <%= p("system_domain") %>
app_domains: [ <%= p("app_domains").join(", ") %> ]
<% if_p("cc.reserved_private_domains") do |reserved| %>
reserved_private_domains: <%= reserved %>
<% end %>

jobs:
global:
Expand Down
3 changes: 3 additions & 0 deletions bosh-templates/cloud_controller_worker.yml.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ external_domain: <%= p("cc.external_host") %>.<%= p("domain") %>
system_domain_organization: <%= p("system_domain_organization") %>
system_domain: <%= p("system_domain") %>
app_domains: [ <%= p("app_domains").join(", ") %> ]
<% if_p("cc.reserved_private_domains") do |reserved| %>
reserved_private_domains: <%= reserved %>
<% end %>

jobs:
global:
Expand Down
6 changes: 5 additions & 1 deletion lib/cloud_controller/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ class Config < VCAP::Config
routing_client_secret: String,
},

optional(:route_services_enabled) => bool
optional(:route_services_enabled) => bool,

optional(:reserved_private_domains) => String,
}
end

Expand All @@ -264,6 +266,8 @@ def configure_components(config)
QuotaDefinition.configure(config)
Stack.configure(config[:stacks_file])

PrivateDomain.configure(config[:reserved_private_domains])

dependency_locator = CloudController::DependencyLocator.instance
nsync_client = Diego::NsyncClient.new(@config)
dependency_locator.register(:nsync_client, nsync_client)
Expand Down
11 changes: 11 additions & 0 deletions spec/fixtures/config/reserved_private_domains.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ===BEGIN ICANN DOMAINS===

// ac : https://en.wikipedia.org/wiki/.ac
ac
com.ac

// xn--jvr189m : 2015-02-26 Amazon EU S.à r.l.
手机

*.wild.card
!a.wild.card
7 changes: 7 additions & 0 deletions spec/unit/lib/cloud_controller/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ module VCAP::CloudController
password: 'password',
},
},

reserved_private_domains: File.join(Paths::FIXTURES, 'config/reserved_private_domains.dat'),
}
end

Expand Down Expand Up @@ -418,6 +420,11 @@ module VCAP::CloudController
Config.configure_components(@test_config)
expect(dependency_locator.stager_client).to be_an_instance_of(VCAP::CloudController::Diego::StagerClient)
end

it 'sets up the reserved private domain' do
expect(PrivateDomain).to receive(:configure).with(@test_config[:reserved_private_domains])
Config.configure_components(@test_config)
end
end
end
end
32 changes: 32 additions & 0 deletions spec/unit/models/runtime/private_domain_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
module VCAP::CloudController
describe PrivateDomain, type: :model do
let(:private_domain) { described_class.make name: 'test.example.com' }
let(:reserved) { nil }

before(:each) do
TestConfig.override({ reserved_private_domains: reserved })
end

it { is_expected.to have_timestamp_columns }

Expand Down Expand Up @@ -70,6 +75,33 @@ module VCAP::CloudController
expect { PrivateDomain.make name: 'bar.foo.com' }.to raise_error(Sequel::ValidationFailed, /overlapping_domain/)
end

context 'with reserved private domains' do
let(:reserved) { File.join(Paths::FIXTURES, 'config/reserved_private_domains.dat') }

it 'handles normal reserved domain names' do
expect { PrivateDomain.make name: 'com.ac' }.to raise_error(Sequel::ValidationFailed, /reserved/)
expect { PrivateDomain.make name: 'a.com.ac' }.to_not raise_error
expect { PrivateDomain.make name: 'scom.ac' }.to_not raise_error
end

it 'handles wildcard reserved domain names' do
expect { PrivateDomain.make name: 'b.wild.card' }.to raise_error(Sequel::ValidationFailed, /reserved/)
expect { PrivateDomain.make name: 'a.b.wild.card' }.to_not raise_error
end

it 'handles exception reserved domain names' do
expect { PrivateDomain.make name: 'a.wild.card' }.to_not raise_error
end

context 'with a missing file' do
let(:reserved) { nil }

it 'raises an error' do
expect { PrivateDomain.configure('bogus') }.to raise_error(Errno::ENOENT)
end
end
end

describe 'total allowed private domains' do
let(:organization) { Organization.make }
let(:org_quota) { organization.quota_definition }
Expand Down