Content Selectors and Docker

Should you wish to not share all Docker components across all teams, we recommend using content selectors in conjunction with access control (specifically the privileges created by content selectors) to manage access to specific content. However, the Docker format has some non-standard complexity to setting up security against the CLI and UI.

Before continuing, note that we provide the instructions in this section with the assumption that you are able to sort the security of your Docker images by name. Below, we use the word team in our examples where team is the representation of that which you are sorting.  For example, it might be sonatype/nexus for this product/project team, or further sonatype/nexus/docker for the Docker-specific parts. If you are unable to do this, this page likely will not help you or your solution will be much more complex than the scenarios given.

REST API vs. Docker Client

Content selectors match a path to the content stored inside of Nexus Repository. For Docker, this is more complex than other formats. 

Any time you perform a client action using Docker client, it will use the actual path. However, if you perform an action through the Nexus Repository REST API, it matches to component name.

When writing content selectors for Docker, they should match both for path name and component name.

For example, if you want a content selector to match to hello-world, then your content selector should use the following:

format == "docker" and path =~ "^(/v2/|/v2/library/)?(hello-world(/.*)?)?$”

Commands

docker login

This command requires access to the /v2/ path and can be established by creating a content selector with the search expression path == "/v2/" as shown here:

Once the content selector is created, a Repository Content Selector privilege with Actions defined with read should be created, as shown below, then assigned to a role and subsequently users.

Access to login likely will need to be combined with other privileges to be useful.

docker search

This command requires access to the /v1/search path and can be established by creating a content selector with the search expression path == "/v1/search" as shown here:

Once the content selector is created, a Repository Content Selector privilege with Actions defined as read should be created, as shown below, then assigned to a role and subsequently users.

Disclaimers

This privilege gives those assigned access to search the entire repository which can be more than you have access to pull/push.

Further, this privilege does not give you access to search anything via UI, instead it is delegating search via the CLI.  How to give permission to search via the UI is defined below.


docker pull (by team)

This command requires that the content selector path be restricted by team. This can be done loosely (e.g., path =~ ".*/team/.*") with "contains team" or strictly (e.g., path =^ "/v2/team/") with "starts with team". Note that for simpler docker packages, you can restrict using library too (e.g., path =^ "/v2/library/hello-world/").

Any of these methods give you the ability to pull any version of components from team.

Here's an example content selector:

Once the content selector is created, a Repository Content Selector privilege with Actions defined as read should be created, as shown below, then assigned to a role and subsequently users.

Content selectors and privileges will need created for each "team".

(info) With security setup in this way, users trying docker pull commands by hash will get unauthorized responses because the hash does not fall in the pattern of the path defined above.

Tip: Browse UI and Content Selector Preview

read action grants permission to the Browse UI but only to manifests and tags (which match the path defined).  Individual layers will not be shown.

The same will reflect in Content Selector preview results.


docker push (by team)

Like docker pull, this command also requires that the content selector path be restricted by team.  This can be done loosely (e.g. path =~ ".*/team/.*") with "contains team" or strictly (e.g. path =^ "/v2/team/") with "starts with team".  Using the simpler library method from docker pull (e.g. path =^ "/v2/library/hello-world/") will not work.

Because the exact same paths can be used if you have docker pull content selectors too, you can reuse them if you've implemented docker pull.  However you need them distinct, you'd create a new content selector like this:

If you are combining permissions, edit your existing privilege Actions to put (comma delinated) add and edit (in addition to read) like so:

If you are not combining, create a new a Repository Content Selector  privilege with Actions defined as add,edit like so:

Then assign the privilege to roles and subsequently users.

Content selectors and privileges will need created (or combined/edited) for each "team".

Search UI

The permissions described in Docker Search do not grant permission to the Search UI.  To gain permission to the Search UI the role needs to have the nx-search-read privilege assigned.  In addition to this to see the items restricted by path, the Action of browse needs to be added.  You can do this by adding (comma delinated) to an existing privilege with the path for your team (e.g. path =^ "/v2/team/", path =~ ".*/team/.*" or path =^ "/v2/library/hello-world/") or by creating a new privilege then assigning that to roles.

Here's an example of the new privilege you would create:

If creating a new privilege, you would assign this privilege to roles and then the roles to users as needed.  If editing the existing privilege, permissions will be granted when you save.