diff --git a/Dockerfile b/Dockerfile index c647697..bbdc8e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:14.04 +FROM ubuntu:16.04 ENV DEBIAN_FRONTEND noninteractive #prevent apt from installing recommended packages @@ -6,11 +6,11 @@ RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/docker-no-reco echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf.d/docker-no-recommends # Install java and tomcat -RUN apt-get update && apt-get install -y tomcat7 openjdk-7-jdk libyaml-perl libfile-slurp-perl && \ +RUN apt-get update && apt-get install -y tomcat7 openjdk-8-jdk libyaml-perl libfile-slurp-perl && \ rm -rf /var/lib/tomcat7/webapps/* && \ rm -rf /var/lib/apt/lists/* -ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64 +ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 ENV CATALINA_HOME /usr/share/tomcat7 ENV CATALINA_BASE /var/lib/tomcat7 diff --git a/README.md b/README.md index 3367fcf..7b9a42e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ +# This repo is a fork version with some enhancement of this awesome repo https://github.com/mkuchin/docker-registry-web + # docker-registry-web Web UI, authentication service and event recorder for private docker registry v2. -[![Docker Stars](https://img.shields.io/docker/stars/hyper/docker-registry-web.svg?maxAge=86400)](https://hub.docker.com/r/hyper/docker-registry-web/) [![Docker Pulls](https://img.shields.io/docker/pulls/hyper/docker-registry-web.svg?maxAge=86400)](https://hub.docker.com/r/hyper/docker-registry-web/) +[![Docker Stars](https://img.shields.io/docker/stars/lukenvn/docker-registry-web.svg?maxAge=86400)](https://hub.docker.com/r/lukenvn/docker-registry-web/) [![Docker Pulls](https://img.shields.io/docker/pulls/lukenvn/docker-registry-web.svg?maxAge=86400)](https://hub.docker.com/r/lukenvn/docker-registry-web/) ## Features: @@ -10,12 +12,12 @@ Web UI, authentication service and event recorder for private docker registry v2 * Optional token based authentication provider with role-based permissions * Docker registry notification recording and audit -### Warning: [this version config](https://github.com/mkuchin/docker-registry-web/blob/master/web-app/WEB-INF/config.yml) is not compatible with configuration of versions prior 0.1.0 - [Migrating configuration from 0.0.4 to 0.1.x](https://github.com/mkuchin/docker-registry-web/wiki/Migrating-configuration) +### Warning: [this version config](https://github.com/lukenvn/docker-registry-web/blob/master/web-app/WEB-INF/config.yml) is not compatible with configuration of versions prior 0.1.0 + [Migrating configuration from 0.0.4 to 0.1.x](https://github.com/lukenvn/docker-registry-web/wiki/Migrating-configuration) ### Docker pull command - docker pull hyper/docker-registry-web + docker pull lukenvn/docker-registry-web ### How to run @@ -24,14 +26,14 @@ Web UI, authentication service and event recorder for private docker registry v2 Do not use _registry_ as registry container name, it will break `REGISTRY_NAME` environment variable. docker run -d -p 5000:5000 --name registry-srv registry:2 - docker run -it -p 8080:8080 --name registry-web --link registry-srv -e REGISTRY_URL=http://registry-srv:5000/v2 -e REGISTRY_NAME=localhost:5000 hyper/docker-registry-web + docker run -it -p 8080:8080 --name registry-web --link registry-srv -e REGISTRY_URL=http://registry-srv:5000/v2 -e REGISTRY_NAME=localhost:5000 lukenvn/docker-registry-web #### Connecting to docker registry with basic authentication and self-signed certificate docker run -it -p 8080:8080 --name registry-web --link registry-srv \ -e REGISTRY_URL=https://registry-srv:5000/v2 \ -e REGISTRY_TRUST_ANY_SSL=true \ -e REGISTRY_BASIC_AUTH="YWRtaW46Y2hhbmdlbWU=" \ - -e REGISTRY_NAME=localhost:5000 hyper/docker-registry-web + -e REGISTRY_NAME=localhost:5000 lukenvn/docker-registry-web #### No authentication, with config file @@ -55,7 +57,7 @@ Do not use _registry_ as registry container name, it will break `REGISTRY_NAME` 2. Run with docker docker run -p 5000:5000 --name registry-srv -d registry:2 - docker run -it -p 8080:8080 --name registry-web --link registry-srv -v $(pwd)/config.yml:/conf/config.yml:ro hyper/docker-registry-web + docker run -it -p 8080:8080 --name registry-web --link registry-srv -v $(pwd)/config.yml:/conf/config.yml:ro lukenvn/docker-registry-web 3. Web UI will be available on `http://localhost:8080` @@ -119,7 +121,7 @@ Do not use _registry_ as registry container name, it will break `REGISTRY_NAME` docker run -v $(pwd)/conf/registry-web.yml:/conf/config.yml:ro \ -v $(pwd)/conf/auth.key:/conf/auth.key -v $(pwd)/db:/data \ - -it -p 8080:8080 --link registry-srv --name registry-web hyper/docker-registry-web + -it -p 8080:8080 --link registry-srv --name registry-web lukenvn/docker-registry-web 6. Web UI will be available on `http://localhost:8080` with default admin user/password `admin/admin`. @@ -139,10 +141,10 @@ User access allows to browse registry, admin access allows to create, delete and UI_DELETE role allows deleting images in the UI based on ACLs. Every non-special role has a list of ACLs, each of ACL grants permission grants permission to `pull`, `pull+push` or `pull+push+delete` -based on IP and image name [glob matching](https://github.com/mkuchin/docker-registry-web/wiki/Glob-matching). +based on IP and image name [glob matching](https://github.com/lukenvn/docker-registry-web/wiki/Glob-matching). For example **read-all** role matches any IP and any image name with glob `*` and grants `pull` permission and **write-all** role grants `pull+push` permission for any IP and any image name. -### [Configuration reference](https://github.com/mkuchin/docker-registry-web/blob/master/web-app/WEB-INF/config.yml) +### [Configuration reference](https://github.com/lukenvn/docker-registry-web/blob/master/web-app/WEB-INF/config.yml) -### [Docker Compose configuration examples](https://github.com/mkuchin/docker-registry-web/tree/master/examples) +### [Docker Compose configuration examples](https://github.com/lukenvn/docker-registry-web/tree/master/examples) diff --git a/examples/auth-enabled/conf/registry-web/config.yml b/examples/auth-enabled/conf/registry-web/config.yml index 4970163..0eaf822 100644 --- a/examples/auth-enabled/conf/registry-web/config.yml +++ b/examples/auth-enabled/conf/registry-web/config.yml @@ -2,6 +2,8 @@ registry: url: http://registry:5000/v2 name: localhost:5000 readonly: false + # with this config the user will not see all the available repos in docker-registry-web + show-permitted-repo-only: true auth: enabled: true key: /conf/auth.key diff --git a/examples/auth-enabled/docker-compose.yml b/examples/auth-enabled/docker-compose.yml index 3afdcf5..1543bcc 100644 --- a/examples/auth-enabled/docker-compose.yml +++ b/examples/auth-enabled/docker-compose.yml @@ -17,7 +17,7 @@ services: - 5000:5000 volumes: - ./conf/registry:/etc/docker/registry:ro - - ./registry:/var/lib/registry + - ./registry:/registry networks: - registry-net diff --git a/examples/nginx-auth-enabled/conf/registry-web/config.yml b/examples/nginx-auth-enabled/conf/registry-web/config.yml index e2b4eef..035ebeb 100644 --- a/examples/nginx-auth-enabled/conf/registry-web/config.yml +++ b/examples/nginx-auth-enabled/conf/registry-web/config.yml @@ -2,6 +2,8 @@ registry: url: http://registry:5000/v2 name: localhost readonly: false + # with this config the user will not see all the available repos in docker-registry-web + show-permitted-repo-only: true auth: enabled: true key: /conf/auth.key diff --git a/examples/nginx-auth-enabled/docker-compose.yml b/examples/nginx-auth-enabled/docker-compose.yml index 39942fe..3cc87c8 100644 --- a/examples/nginx-auth-enabled/docker-compose.yml +++ b/examples/nginx-auth-enabled/docker-compose.yml @@ -28,9 +28,9 @@ services: - 127.0.0.1:5000:5000 volumes: - ./conf/registry:/etc/docker/registry:ro - - ./registry:/var/lib/registry + - ./registry:/registry networks: - registry-net networks: - registry-net: \ No newline at end of file + registry-net: diff --git a/grails-app/conf/config.yml b/grails-app/conf/config.yml index 5fdcaa4..36521a4 100644 --- a/grails-app/conf/config.yml +++ b/grails-app/conf/config.yml @@ -1,10 +1,12 @@ #dev config registry: -# Docker registry url - url: 'http://localhost:5001/v2/' - name: 'hub.devspire.com.au' + # Docker registry url + url: http://localhost:5000/v2/ + name: localhost:5000 + # enable showing permitted repo only on docker registry web + show-permitted-repo-only: true auth: enabled: true - #issuer: 'xxx' - key: ssl/key-dec.pem \ No newline at end of file + issuer: test + key: /Users/ngovannhung/Downloads/docker-registry-web-master/grails-app/conf/auth.key \ No newline at end of file diff --git a/grails-app/controllers/docker/registry/web/RepositoryController.groovy b/grails-app/controllers/docker/registry/web/RepositoryController.groovy index 2e12a38..d318c02 100644 --- a/grails-app/controllers/docker/registry/web/RepositoryController.groovy +++ b/grails-app/controllers/docker/registry/web/RepositoryController.groovy @@ -1,5 +1,8 @@ package docker.registry.web +import docker.registry.AccessControl +import docker.registry.Role +import docker.registry.RoleAccess import groovy.json.JsonSlurper import org.springframework.beans.factory.annotation.Value @@ -11,8 +14,12 @@ class RepositoryController { @Value('${registry.name}') String registryName + @Value('${registry.show-permitted-repo-only}') + boolean enableShowPermittedRepoOnly + def restService def authService + def springSecurityService; //{"Type":"registry","Name":"catalog","Action":"*"} def index() { @@ -22,6 +29,8 @@ class RepositoryController { boolean hasNext = false def message def url = "_catalog?n=${recordsPerPage}" + + try { if (params.start) { url += "&last=${params.start}" @@ -37,8 +46,12 @@ class RepositoryController { pagination = hasNext || params.prev != null def repos = restResponse.json.repositories next = repos ? repos.last() : null + def permittedRepos = repos + if (enableShowPermittedRepoOnly == true) { + permittedRepos = filterPermittedRepoOnly(repos) + } - repoCount = repos.collect { name -> + repoCount = permittedRepos.collect { name -> def tagsCount = getTagList(name).size() [name: name, tags: tagsCount] } @@ -49,6 +62,26 @@ class RepositoryController { [repos: repoCount, pagination: pagination, next: next, prev: params.start, hasNext: hasNext, registryName: registryName, message: message] } + private List filterPermittedRepoOnly(repos) { + def currentUser = springSecurityService.currentUser + def roles = currentUser.authorities.collect { role -> + Role.findByAuthority(role.authority) + }.findAll { it } + def acls = roles.collect { role -> + RoleAccess.findAllByRole(role).acl + }.flatten() + repos.findAll { name -> hasPermission(acls, name) } + } + + def hasPermission(acls,name){ + + for (AccessControl element : acls) { + if (GlobMatcher.check(element.name, name)) { + return true; + } + } + return false + } def tags() { String name = params.id.decodeURL() def tags = getTags(name) diff --git a/grails-app/controllers/docker/registry/web/UserController.groovy b/grails-app/controllers/docker/registry/web/UserController.groovy index 5a02899..50f7a79 100644 --- a/grails-app/controllers/docker/registry/web/UserController.groovy +++ b/grails-app/controllers/docker/registry/web/UserController.groovy @@ -61,7 +61,7 @@ class UserController { user.accountLocked = params.accountLocked as boolean //update password only if it entered if (params.password) { - user.password = params.password + user.password = params.password[1] } if (user.isDirty()) { diff --git a/grails-app/services/docker/registry/web/AuthService.groovy b/grails-app/services/docker/registry/web/AuthService.groovy index 1fd98b4..5d4c5f7 100644 --- a/grails-app/services/docker/registry/web/AuthService.groovy +++ b/grails-app/services/docker/registry/web/AuthService.groovy @@ -74,6 +74,18 @@ class AuthService { }.actions.flatten().unique() log.info "Granting permissions: $actions" } + //scope: registry:catalog:* + if(aclList && scope && scope.type == 'registry' && scope.name == 'catalog' ){ + actions = aclList.collect { AccessControl acl -> + def scopeActions = scope.actions; + if(scopeActions.size()>0){ + if (GlobMatcher.check(acl.name, scopeActions[0])){ + return scopeActions[0] + }else + return AccessLevel.NONE.actions; + } + }.flatten().unique() + } actions } diff --git a/grails-app/views/layouts/main.gsp b/grails-app/views/layouts/main.gsp index a7dccf5..bcdefa6 100644 --- a/grails-app/views/layouts/main.gsp +++ b/grails-app/views/layouts/main.gsp @@ -42,14 +42,15 @@
  • Roles -
  • - +
  • Events
  • Status
  • + +