Adding registry endpoint authorization

This commit is contained in:
Andre Guedes 2016-12-13 23:42:43 -02:00
parent eed0b85ad0
commit 246df2bd11
12 changed files with 133 additions and 17 deletions

View file

@ -29,6 +29,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
redirect_to :back redirect_to :back
end 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 def clear_repository_check_states
RepositoryCheck::ClearWorker.perform_async RepositoryCheck::ClearWorker.perform_async

View file

@ -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

View file

@ -4,6 +4,7 @@ class ApplicationSetting < ActiveRecord::Base
add_authentication_token_field :runners_registration_token add_authentication_token_field :runners_registration_token
add_authentication_token_field :health_check_access_token add_authentication_token_field :health_check_access_token
add_authentication_token_field :container_registry_access_token
CACHE_KEY = 'application_setting.last' CACHE_KEY = 'application_setting.last'
DOMAIN_LIST_SEPARATOR = %r{\s*[,;]\s* # comma or semicolon, optionally surrounded by whitespace 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_runners_registration_token
before_save :ensure_health_check_access_token before_save :ensure_health_check_access_token
before_save :ensure_container_registry_access_token
after_commit do after_commit do
Rails.cache.write(CACHE_KEY, self) Rails.cache.write(CACHE_KEY, self)
@ -276,6 +278,10 @@ class ApplicationSetting < ActiveRecord::Base
ensure_health_check_access_token! ensure_health_check_access_token!
end end
def container_registry_access_token
ensure_container_registry_access_token!
end
def sidekiq_throttling_enabled? def sidekiq_throttling_enabled?
return false unless sidekiq_throttling_column_exists? return false unless sidekiq_throttling_column_exists?

View file

@ -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

View file

@ -27,3 +27,7 @@
= link_to admin_runners_path, title: 'Runners' do = link_to admin_runners_path, title: 'Runners' do
%span %span
Runners Runners
= nav_link path: 'container_registry#show' do
= link_to admin_container_registry_path, title: 'Registry' do
%span
Registry

View file

@ -58,6 +58,7 @@ namespace :admin do
resource :background_jobs, controller: 'background_jobs', only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show]
resource :system_info, controller: 'system_info', only: [:show] resource :system_info, controller: 'system_info', only: [:show]
resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ }
resource :container_registry, controller: 'container_registry', only: [:show]
resources :projects, only: [:index] resources :projects, only: [:index]
@ -88,6 +89,7 @@ namespace :admin do
resources :services, only: [:index, :edit, :update] resources :services, only: [:index, :edit, :update]
put :reset_runners_token put :reset_runners_token
put :reset_health_check_token put :reset_health_check_token
put :reset_container_registry_token
put :clear_repository_check_states put :clear_repository_check_states
end end

View file

@ -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

View file

@ -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] At the absolute minimum, make sure your [Registry configuration][registry-auth]
has `container_registry` as the service and `https://gitlab.example.com/jwt/auth` has `container_registry` as the service and `https://gitlab.example.com/jwt/auth`
as the realm: as the realm.
``` ```
auth: auth:
@ -87,6 +87,23 @@ auth:
rootcertbundle: /root/certs/certbundle 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 ## Container Registry domain configuration
There are two ways you can configure the Registry's external domain. 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 8.8 ([source docs][8-8-docs])**
- GitLab Container Registry feature was introduced. - GitLab Container Registry feature was introduced.
i
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure [reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
[restart gitlab]: restart_gitlab.md#installations-from-source [restart gitlab]: restart_gitlab.md#installations-from-source
[wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate [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 [storage-config]: https://docs.docker.com/registry/configuration/#storage
[registry-http-config]: https://docs.docker.com/registry/configuration/#http [registry-http-config]: https://docs.docker.com/registry/configuration/#http
[registry-auth]: https://docs.docker.com/registry/configuration/#auth [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 [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 [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 [registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl

View file

@ -299,8 +299,8 @@ could look like:
stage: build stage: build
script: script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com
- docker build -t registry.example.com/group/project:latest . - docker build -t registry.example.com/group/project/image:latest .
- docker push registry.example.com/group/project: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 You have to use the special `gitlab-ci-token` user created for you in order to
@ -350,8 +350,8 @@ stages:
- deploy - deploy
variables: variables:
CONTAINER_TEST_IMAGE: registry.example.com/my-group/my-project:$CI_BUILD_REF_NAME 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:latest CONTAINER_RELEASE_IMAGE: registry.example.com/my-group/my-project/my-image:latest
before_script: before_script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.example.com

View file

@ -10,6 +10,7 @@
- Starting from GitLab 8.12, if you have 2FA enabled in your account, you need - 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 to pass a personal access token instead of your password in order to login to
GitLab's Container Registry. 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 With the Docker Container Registry integrated into GitLab, every project can
have its own space to store its Docker images. 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: that is hosted on GitLab:
``` ```
docker build -t registry.example.com/group/project . docker build -t registry.example.com/group/project/image .
docker push registry.example.com/group/project docker push registry.example.com/group/project/image
``` ```
Your image will be named after the following scheme: Your image will be named after the following scheme:
``` ```
<registry URL>/<namespace>/<project> <registry URL>/<namespace>/<project>/<image>
``` ```
As such, the name of the image is unique, but you can differentiate the images
using tags.
## Use images from GitLab Container Registry ## Use images from GitLab Container Registry
To download and run a container from images hosted in GitLab Container Registry, To download and run a container from images hosted in GitLab Container Registry,
use `docker run`: 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 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 This view will show you all tags in your project and will easily allow you to
delete them. 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 ## 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: 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 dc5e59c14160: Pushing [==================================================>] 14.85 kB
03c20c1a019a: Pushing [==================================================>] 2.048 kB 03c20c1a019a: Pushing [==================================================>] 2.048 kB
a08f14ef632e: 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 ```sh
docker login s3-testing.myregistry.com:4567 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: In the example above, we see the following trace on the mitmproxy window:

View file

@ -111,6 +111,16 @@ module API
end end
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! def authenticated_as_admin!
authenticate! authenticate!
forbidden! unless current_user.is_admin? forbidden! unless current_user.is_admin?

View file

@ -1,7 +1,7 @@
module API module API
# RegistryEvents API # RegistryEvents API
class RegistryEvents < Grape::API class RegistryEvents < Grape::API
# before { authenticate! } before { authenticate_container_registry_access_token! }
content_type :json, 'application/vnd.docker.distribution.events.v1+json' content_type :json, 'application/vnd.docker.distribution.events.v1+json'