diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index b0f5d4a9933..fb6df1a06d2 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -29,6 +29,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController redirect_to :back end + def reset_container_registry_token + @application_setting.reset_container_registry_access_token! + flash[:notice] = 'New container registry access token has been generated!' + redirect_to :back + end + def clear_repository_check_states RepositoryCheck::ClearWorker.perform_async diff --git a/app/controllers/admin/container_registry_controller.rb b/app/controllers/admin/container_registry_controller.rb new file mode 100644 index 00000000000..265c032c67d --- /dev/null +++ b/app/controllers/admin/container_registry_controller.rb @@ -0,0 +1,11 @@ +class Admin::ContainerRegistryController < Admin::ApplicationController + def show + @access_token = container_registry_access_token + end + + private + + def container_registry_access_token + current_application_settings.container_registry_access_token + end +end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 74b358d8c40..b94a71e1ea7 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -4,6 +4,7 @@ class ApplicationSetting < ActiveRecord::Base add_authentication_token_field :runners_registration_token add_authentication_token_field :health_check_access_token + add_authentication_token_field :container_registry_access_token CACHE_KEY = 'application_setting.last' DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace @@ -141,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base before_save :ensure_runners_registration_token before_save :ensure_health_check_access_token + before_save :ensure_container_registry_access_token after_commit do Rails.cache.write(CACHE_KEY, self) @@ -276,6 +278,10 @@ class ApplicationSetting < ActiveRecord::Base ensure_health_check_access_token! end + def container_registry_access_token + ensure_container_registry_access_token! + end + def sidekiq_throttling_enabled? return false unless sidekiq_throttling_column_exists? diff --git a/app/views/admin/container_registry/show.html.haml b/app/views/admin/container_registry/show.html.haml new file mode 100644 index 00000000000..8803eddda69 --- /dev/null +++ b/app/views/admin/container_registry/show.html.haml @@ -0,0 +1,31 @@ +- @no_container = true += render "admin/dashboard/head" + +%div{ class: container_class } + + %p.prepend-top-default + %span + To properly configure the Container Registry you should add the following + access token to the Docker Registry config.yml as follows: + %pre + %code + :plain + notifications: + endpoints: + - ... + headers: + X-Registry-Token: [#{@access_token}] + %br + Access token is + %code{ id: 'registry-token' } #{@access_token} + + .bs-callout.clearfix + .pull-left + %p + You can reset container registry access token by pressing the button below. + %p + = button_to reset_container_registry_token_admin_application_settings_path, + method: :put, class: 'btn btn-default', + data: { confirm: 'Are you sure you want to reset container registry token?' } do + = icon('refresh') + Reset container registry access token diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml index 7893c1dee97..dbd039547fa 100644 --- a/app/views/admin/dashboard/_head.html.haml +++ b/app/views/admin/dashboard/_head.html.haml @@ -27,3 +27,7 @@ = link_to admin_runners_path, title: 'Runners' do %span Runners + = nav_link path: 'container_registry#show' do + = link_to admin_container_registry_path, title: 'Registry' do + %span + Registry diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 8e99239f350..b09c05826a7 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -58,6 +58,7 @@ namespace :admin do resource :background_jobs, controller: 'background_jobs', only: [:show] resource :system_info, controller: 'system_info', only: [:show] resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } + resource :container_registry, controller: 'container_registry', only: [:show] resources :projects, only: [:index] @@ -88,6 +89,7 @@ namespace :admin do resources :services, only: [:index, :edit, :update] put :reset_runners_token put :reset_health_check_token + put :reset_container_registry_token put :clear_repository_check_states end diff --git a/db/migrate/20161213212947_add_container_registry_access_token_to_application_settings.rb b/db/migrate/20161213212947_add_container_registry_access_token_to_application_settings.rb new file mode 100644 index 00000000000..f89f9b00a5f --- /dev/null +++ b/db/migrate/20161213212947_add_container_registry_access_token_to_application_settings.rb @@ -0,0 +1,29 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddContainerRegistryAccessTokenToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + # When a migration requires downtime you **must** uncomment the following + # constant and define a short and easy to understand explanation as to why the + # migration requires downtime. + # DOWNTIME_REASON = '' + + # When using the methods "add_concurrent_index" or "add_column_with_default" + # you must disable the use of transactions as these methods can not run in an + # existing transaction. When using "add_concurrent_index" make sure that this + # method is the _only_ method called in the migration, any other changes + # should go in a separate migration. This ensures that upon failure _only_ the + # index creation fails and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + # disable_ddl_transaction! + + def change + add_column :application_settings, :container_registry_access_token, :string + end +end diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md index a6300e18dc0..14795601246 100644 --- a/doc/administration/container_registry.md +++ b/doc/administration/container_registry.md @@ -76,7 +76,7 @@ you modify its settings. Read the upstream documentation on how to achieve that. At the absolute minimum, make sure your [Registry configuration][registry-auth] has `container_registry` as the service and `https://gitlab.example.com/jwt/auth` -as the realm: +as the realm. ``` auth: @@ -87,6 +87,23 @@ auth: rootcertbundle: /root/certs/certbundle ``` +Also a notification endpoint must be configured with the token from +Admin Area -> Overview -> Registry (`/admin/container_registry`) like in the following sample: + +``` +notifications: + endpoints: + - name: listener + url: https://gitlab.example.com/api/v3/registry_events + headers: + X-Registry-Token: [57Cx95fc2zHFh93VTiGD] + timeout: 500ms + threshold: 5 + backoff: 1s +``` + +Check the [Registry endpoint configuration][registry-endpoint] for details. + ## Container Registry domain configuration There are two ways you can configure the Registry's external domain. @@ -477,7 +494,7 @@ configurable in future releases. **GitLab 8.8 ([source docs][8-8-docs])** - GitLab Container Registry feature was introduced. - +i [reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure [restart gitlab]: restart_gitlab.md#installations-from-source [wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate @@ -487,6 +504,7 @@ configurable in future releases. [storage-config]: https://docs.docker.com/registry/configuration/#storage [registry-http-config]: https://docs.docker.com/registry/configuration/#http [registry-auth]: https://docs.docker.com/registry/configuration/#auth +[registry-endpoint]: https://docs.docker.com/registry/notifications/#/configuration [token-config]: https://docs.docker.com/registry/configuration/#token [8-8-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/doc/administration/container_registry.md [registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 8620984d40d..6ae6269b28a 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -299,8 +299,8 @@ could look like: stage: build script: - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com - - docker build -t registry.example.com/group/project:latest . - - docker push registry.example.com/group/project:latest + - docker build -t registry.example.com/group/project/image:latest . + - docker push registry.example.com/group/project/image:latest ``` You have to use the special `gitlab-ci-token` user created for you in order to @@ -350,8 +350,8 @@ stages: - deploy variables: - CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project:$CI_BUILD_REF_NAME - CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project:latest + CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project/my-image:$CI_BUILD_REF_NAME + CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project/my-image:latest before_script: - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md index 91b35c73b34..eada8e04227 100644 --- a/doc/user/project/container_registry.md +++ b/doc/user/project/container_registry.md @@ -10,6 +10,7 @@ - Starting from GitLab 8.12, if you have 2FA enabled in your account, you need to pass a personal access token instead of your password in order to login to GitLab's Container Registry. +- Multiple level image names support was added in GitLab ?8.15? With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images. @@ -54,26 +55,23 @@ sure that you are using the Registry URL with the namespace and project name that is hosted on GitLab: ``` -docker build -t registry.example.com/group/project . -docker push registry.example.com/group/project +docker build -t registry.example.com/group/project/image . +docker push registry.example.com/group/project/image ``` Your image will be named after the following scheme: ``` -// +/// ``` -As such, the name of the image is unique, but you can differentiate the images -using tags. - ## Use images from GitLab Container Registry To download and run a container from images hosted in GitLab Container Registry, use `docker run`: ``` -docker run [options] registry.example.com/group/project [arguments] +docker run [options] registry.example.com/group/project/image [arguments] ``` For more information on running Docker containers, visit the @@ -87,7 +85,8 @@ and click **Registry** in the project menu. This view will show you all tags in your project and will easily allow you to delete them. -![Container Registry panel](img/container_registry_panel.png) +![Container Registry panel](image-needs-update) +[//]: # (img/container_registry_panel.png) ## Build and push images using GitLab CI @@ -136,7 +135,7 @@ A user attempted to enable an S3-backed Registry. The `docker login` step went fine. However, when pushing an image, the output showed: ``` -The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test] +The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test/docker-image] dc5e59c14160: Pushing [==================================================>] 14.85 kB 03c20c1a019a: Pushing [==================================================>] 2.048 kB a08f14ef632e: Pushing [==================================================>] 2.048 kB @@ -229,7 +228,7 @@ a container image. You may need to run as root to do this. For example: ```sh docker login s3-testing.myregistry.com:4567 -docker push s3-testing.myregistry.com:4567/root/docker-test +docker push s3-testing.myregistry.com:4567/root/docker-test/docker-image ``` In the example above, we see the following trace on the mitmproxy window: diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index a1db2099693..0fd2b1587e3 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -111,6 +111,16 @@ module API end end + def authenticate_container_registry_access_token! + token = request.headers['X-Registry-Token'] + unless token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare( + token, + current_application_settings.container_registry_access_token + ) + unauthorized! + end + end + def authenticated_as_admin! authenticate! forbidden! unless current_user.is_admin? diff --git a/lib/api/registry_events.rb b/lib/api/registry_events.rb index dc7279d2b75..e52433339eb 100644 --- a/lib/api/registry_events.rb +++ b/lib/api/registry_events.rb @@ -1,7 +1,7 @@ module API # RegistryEvents API class RegistryEvents < Grape::API - # before { authenticate! } + before { authenticate_container_registry_access_token! } content_type :json, 'application/vnd.docker.distribution.events.v1+json'