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 in the image below:
After creating the content selector, create a Repository Content Selector privilege; in the Actions section, enter "read" to grant read permissions. Assign this privilege to a role associated with appropriate users.
You will likely need to combine this with other privileges.
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 in the image below:
After creating the content selector, create a Repository Content Selector privilege; in the Actions section, enter "read" to grant read permissions. Assign this privilege to a role associated with appropriate users.
Warning
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:
After creating the content selector, create a Repository Content Selector privilege; in the Actions section, enter "read" to grant read permissions. Assign this privilege to a role associated with appropriate users.
Content selectors and privileges will need created for each "team".
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.
Note
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 make it "read,add,edit
" (comma-delimited with no whitespace).
If you are not combining, create a new a Repository Content Selector privilege with Actions defined as "add,edit
" as shown below.
Then, assign the privilege to the appropriate roles.
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.