Project

General

Profile

Revision 9ea40591

Added by Daniel Lobato Garcia over 6 years ago

Fixes #14181 - Validate registry URL and attempt login

In order to avoid users trying to create containers in an external
registry that doesn't exist, we should provide some preventative
measures.

View differences:

app/models/docker_registry.rb
3 3
  include Taxonomix
4 4
  include Encryptable
5 5

  
6
  attr_accessible :name, :url, :username, :password, :locations, :organizations
7

  
8 6
  has_many :containers, :foreign_key => "registry_id", :dependent => :destroy
9 7
  encrypts :password
10 8

  
11
  attr_accessible :name, :url, :username, :password, :locations, :organizations
9
  attr_accessible :name, :url, :username, :password, :locations, :organizations,
10
    :description
12 11

  
13 12
  validates_lengths_from_database
14 13
  validates :name, :presence => true, :uniqueness => true
15
  validates :url,  :presence => true, :uniqueness => true
14
  validates :url,  :presence => true, :uniqueness => true,
15
    :url_schema => ['http', 'https']
16
  validate :attempt_login
16 17

  
17 18
  scoped_search :on => :name, :complete_value => true
18 19
  scoped_search :on => :url
......
37 38
  def self.humanize_class_name(_name = nil)
38 39
    _("Docker/Registry")
39 40
  end
41

  
42
  private
43

  
44
  def attempt_login
45
    credentials = { 'username' => username, 'password' => password }
46
    connection = ::Docker::Connection.new(
47
      url,
48
      credentials)
49
    ::Docker.authenticate!(credentials, connection)
50
  rescue => e
51
    errors.add(:base, _('Unable to log in to this Docker Registry - %s') % e)
52
  end
40 53
end
app/views/registries/index.html.erb
11 11
    <th class="text-center"><%= sort :name, :as => _("Name") %></th>
12 12
    <th class="hidden-tablet hidden-xs text-center"><%= sort :url, :as => _("Url") %></th>
13 13
    <th class="hidden-tablet hidden-xs text-center"><%= _("Description") %></th>
14
    <th></th>
14
    <th><%= _('Actions') %></th>
15 15
  </tr>
16 16
  </thead>
17 17

  
......
20 20
        <td><%= link_to_if_authorized trunc_with_tooltip(r.name), hash_for_edit_registry_path(:id => r).merge(:auth_object => r, :authorizer => authorizer) %></td>
21 21
        <td class="hidden-tablet hidden-xs text-center"><%= trunc_with_tooltip(r.url) %></td>
22 22
        <td class="hidden-tablet hidden-xs text-center"><%= trunc_with_tooltip(r.description) %></td>
23
        <td><%= display_delete_if_authorized hash_for_registry_path(:id => r).merge(:auth_object => r, :authorizer => authorizer), :confirm => _("Delete %s?") % r.name %></td>
23
        <td><%= action_buttons(
24
          display_delete_if_authorized hash_for_registry_path(:id => r).
25
          merge(:auth_object => r, :authorizer => authorizer),
26
          :confirm => _("Delete %s?") % r.name) %></td>
24 27
      </tr>
25 28
  <% end %>
26 29
</table>
test/factories/docker_registry.rb
6 6
    sequence(:password) { |n| "password#{n}" }
7 7
  end
8 8

  
9
  after(:build) do |registry|
10
    registry.stubs(:attempt_login)
11
  end
12

  
9 13
  trait :with_location do
10 14
    locations { [FactoryGirl.build(:location)] }
11 15
  end
test/functionals/api/v2/registries_controller_test.rb
24 24

  
25 25
      test 'creates a new registry with valid params' do
26 26
        docker_attrs = FactoryGirl.attributes_for(:docker_registry)
27
        DockerRegistry.any_instance.stubs(:attempt_login)
27 28
        post :create, :registry => docker_attrs
28 29
        assert_response :success
29 30
      end
......
41 42
      end
42 43

  
43 44
      test 'update a docker registry' do
45
        DockerRegistry.any_instance.stubs(:attempt_login)
44 46
        put :update, :id => @registry.id, :registry => { :name => 'hello_world' }
45 47
        assert_response :success
46 48
        assert DockerRegistry.exists?(:name => 'hello_world')
test/units/docker_registry_test.rb
24 24
    assert registry.is_decryptable?(registry.password_in_db)
25 25
  end
26 26

  
27
  %w(name url).each do |property|
28
    test "registries need a #{property}" do
29
      refute FactoryGirl.build(:docker_registry, property.to_sym => '').valid?
27
  should validate_presence_of(:name)
28
  should validate_presence_of(:url)
29
  should validate_uniqueness_of(:name)
30
  should validate_uniqueness_of(:url)
31

  
32
  context 'attempt to login' do
33
    setup do
34
      @registry = FactoryGirl.build(:docker_registry)
35
      @registry.unstub(:attempt_login)
36
    end
37

  
38
    test 'before creating a registry' do
39
      ::Docker.expects(:authenticate!)
40
      assert @registry.valid?
41
    end
42

  
43
    test 'display errors in case authentication failed' do
44
      ::Docker.expects(:authenticate!).
45
        raises(Docker::Error::AuthenticationError)
46
      refute @registry.valid?
30 47
    end
31 48
  end
32 49
end

Also available in: Unified diff