Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rootless managing of additional host groups #18333

Closed
zeehio opened this issue Apr 25, 2023 · 21 comments · Fixed by #18713
Closed

Rootless managing of additional host groups #18333

zeehio opened this issue Apr 25, 2023 · 21 comments · Fixed by #18713
Labels
kind/feature Categorizes issue or PR as related to a new feature. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.

Comments

@zeehio
Copy link
Contributor

zeehio commented Apr 25, 2023

Feature request description

This feature request describes how podman could allow rootless management of
additional host groups using better semantics.

One of the current issues with --group-add keep-groups is that while groups
are added, the groups are not mapped, so when listing the groups or a
mounted volume the overflowgid nobody appears. This is confusing.

Besides, some container images need the users to be mapped to operate, for
instance because they create processes based on user logins into the container and
those created processes do not have the unmapped groups set (because they
can't appear in the container's /etc/groups). As an example the rocker/rstudio image
expects users to login to rstudio server through a web interface, and the web logged in user
does not have those groups kept.

Suggest potential solution

This problem can be addressed if the system administrator is willing to give
some additional trust to users (giving the group as a subordinate GID) and
if podman improves its semantics a bit. This is what this feature request is
about.

Asking permission to the system administrator

The system administrator is able to subordinate arbitrary GID usage to a user
through /etc/subgid.

The most common usage of subordinate GIDs is for the sysadmin to give a large
non-overlapping chunk of unused GIDs to each user. Large GIDs are usually available
so we can easily give them away to users.

However, the sysadmin may consider giving as well an existing GID as subordinate to
several users. These users can act as if they owned that GID.

$ cat /etc/subgid

alice:100000:50000
alice:1001:1

Reads as:

The sysadmin grants a block of 50k GIDs, starting at 100000 to user alice.
The sysadmin grants GID 1001 to user alice.

This has security implications, as it essentially means that user alice can
"impersonate" GID 1001.

Telling rootless podman to map GID 1001

To run a container, we need to be able to act as if we had many users and groups
available. For instance, container images may include files owned by different
users and groups and as a regular user we should be able to create and manage
those files. The way to do this is for us (regular users) to create a mapping
between the UIDs and GIDs our container needs (or may need) and a subordinate
UID (GID) range we have.

By default, we may also want to map the root user and root group to our UID/GID
at the host.

This is what rootless podman essentially does:

container GID host GID Comment
0 $(id -g) Map our GID to the root GID in the container
1 1st subid Any GID our container needs to use goes to
2 2nd subid our subordinate block of GIDs
n nth subid

There is no need for podman to map all the subordinate GIDs we have, as long
as all the GIDs the container needs are mapped to some GID we have.

What we would like to do is to have control over host GID 1001. However, we
would like to map it not to an arbitrary GID in the 1-n range, but to a higher stable
GID the container does not actually use.

By choosing to map to a high GID (e.g. container GID 100000+1001), we avoid the risk of
overlapping with GIDs the container needs.

container GID host GID Comment
0 $(id -g) Map our GID to the root GID in the container
1 1st subid Any GID our container needs to use goes to
2 2nd subid our 50k subordinate block of GIDs
n nth subid
101001 1001 A host group we want to access and we have

Podman should add a group entry into the containers /etc/groups, with
the same group name as the host group 1001, with group id 101001 and with
the root user (or whatever user we have mapped onto) as a member, if we are
members of group 1001 in the host.

Suggested improvement

Semantically, it would be helpful defining something in containers.conf that
would tell podman to use host GID 1001 as a "higher container GID", that would not
collide with existing GIDs in the container image, and let podman add the
corresponding entry in /etc/groups.

For instance, the containers.conf could have a field like:

[containers]

# List the subordinate group IDs that should be mapped as additional groups
# in the container

local_group_mappings = [
 1001
]

local_group_offset = 100000

If 1001 is in the subgid for the user running the container, this setting would tell podman to map
1001 to local_group_offset+1001.

Have you considered any alternatives?

Currently podman treats all subordinate GIDs the same. This means that with
the /etc/subgid defined above, podman would map the host group 1001 to
the container GID 1, and the rest of subordinate GIDs would follow.

This is confusing, because GID1 is usually assigned in many containers and it
is defined as the bin or daemon group or some other system group.

Besides, as proven in the reproducible example below, the usage of --gidmap is not invariant to changes on subgids, making the scripts of the rootless user unnecessarily dependant on the subordinate GIDs available.

Additional context

No response

@zeehio zeehio added the kind/feature Categorizes issue or PR as related to a new feature. label Apr 25, 2023
@Luap99
Copy link
Member

Luap99 commented Apr 25, 2023

There is --uidmap and --gidmap, so you can already set any mapping you would like.

@zeehio
Copy link
Contributor Author

zeehio commented Apr 25, 2023

There is --uidmap and --gidmap, so you can already set any mapping you would like.

Kind of, but not really:

According to https://docs.podman.io/en/latest/markdown/podman-run.1.html#uidmap-container-uid-from-uid-amount, --uidmap and --gidmap when used on rootless podman, they only modify the intermediate UID->container UID mapping, but not the host UID -> intermediate UID mapping.

My point here is that, as a rootless podman user:

  • The --gidmap I need to provide to mount a specific host GID (e.g GID 2000) into a specific container GID (e.g. 100000) depends on the intermediate UID mapping, which I do not control.
  • The intermediate mapping is set by podman, based on the full range of subordinate GIDs available.
  • The subordinate GIDs available to me depend on my sysadmin, and they may change (e.g. because the sysadmin subordinates an additional GID to me, of a secondary group of GID 1500). My intermediate GIDs will all shift as a result making all my scripts invalid.

Since I can't rely on the first intermediate mapping being stable (because my sysadmin may trust me with some extra subordinate ids), my usage of --gidmap is not stable and its usability becomes very poor.

Reproducible example:

# Create a sample directory tree
mkdir /tmp/test1
mkdir /tmp/test1/folder_gid_1001
mkdir /tmp/test1/folder_gid_1002
sudo chgrp 1001 /tmp/test1/folder_gid_1001
sudo chgrp 1002 /tmp/test1/folder_gid_1002
ls -lisan /tmp/test1

ls-host

$cat /etc/subgid
sergio:100000:65536
sergio:1002:1

List files through podman using uidmap and gidmap:

$ podman run \
  --rm \
  -v /tmp/test1:/workdir \
  --uidmap "0:0:65535" \
  --gidmap "0:0:1" \
  --gidmap "100000:1:1" \
  --gidmap "1:2:65534" \
  alpine ls -lisan /workdir

imatge

  • host gid 1001 is mapped to nobody (65534)
  • host gid 1002 is mapped to container gid 100000 as intended (since 100000:1:1 refers to the "first intermediate GID")

My sysadmin adds gid 1001 as subordinate GID

$ cat /etc/subgid
sergio:100000:65536

sergio:1002:1
sergio:1001:1

imatge

My script is now invalid, since the gidmap has changed:

  • host gid 1001 is mapped to container gid 100000
  • host gid 1002 is mapped to container gid 1

@Luap99
Copy link
Member

Luap99 commented Apr 25, 2023

I am pretty sure the intermediate mapping is deterministic and depends on the order in /etc/sub?id, you can always check with podman unshare cat /proc/self/gid_map.

Since there is only ever one intermediate namespace (pause process) there is no way to check for an image at the point where we create the namespace to see that the mapping will not conflict with an existing groups in the image.

@giuseppe WDYT?

@zeehio
Copy link
Contributor Author

zeehio commented Apr 25, 2023

Thanks for the feedback @Luap99. I added a reproducible example to hopefully clarify the issue.

I see your point. I can use podman unshare cat /proc/self/gid_map to check what's the current intermediate mapping.

However dealing with groups in this way in a script seems a bit error prone to me 😓

And besides I seem to need to provide the full list of --gidmap and --uidmap. I have learned how to do this, but in my humble opinion it is not very user friendly for a regular rootless user.

@giuseppe
Copy link
Member

@giuseppe WDYT?

that is correct. The user namespace is used as the parent for any Podman operation, so it has no knowledge of the images that are you going to use. You need to parse the /etc/subgid in the podman unshare environment if you want to map to a specific value on the host

@zeehio
Copy link
Contributor Author

zeehio commented Apr 26, 2023

My point is that the first mapping podman makes by default is not very reasonable when there are low subordinated ids.

It is reasonable for podman to assume that subordinate ids above 99999 are meant to be unused at the host and available to be used as low IDs at the container. But I do not think it is reasonable for podman to assume that with low subordinate ids, since they are usually used at the host for something.

Low IDs typically correspond to some host user or group, and therefore they should be mapped to predictable container IDs. I argue that a good default range for that mapping is to offset the host ID by a large number (e.g. 100 000). This yields a symmetric behaviour between mappings at the host and at the container, because 100 000 is also the default starting range for assigning unused subordinate ids:

Host IDs Container IDs Reason
root nobody We do not want rootless containers to impersonate root in the host
user root We want the user to have root-like behaviour in the container
≥ 100 000 <100 000 Containers need to use low IDs, and high host IDs are unused. Mapping order is not usually that relevant since assigned chunks don't change often
<100 000 ≥ 100 000 We want to give access to the container to a host ID. Assign containerID=hostID+100000 so the mapping is systematic

I do not have go experience and I am not familiar with podman's source code, but I would be willing to do my best to attempt to provide a pull request if you think this feature makes sense. Some directions would be very welcome

@giuseppe
Copy link
Member

it is too late to change the mappings we perform, some users might be depending on that, and it is the same mapping done by unshare -r --map-auto.

We usually need to have a root inside the user namespace because otherwise all the files from the image owned by root will show up as owned by nobody.

I suggest you take a look at the --userns=nomap that won't map your user inside the container

@zeehio
Copy link
Contributor Author

zeehio commented Apr 26, 2023

it is too late to change the mappings we perform, some users might be depending on that,

I understand your desire to preserve backwards compatibility. Please consider that:

  • Most of the users only have one subordinate block with high host IDs and therefore would not be affected by this
  • The rest of the users have manually added their subordinate IDs (e.g. adding an additional block) and may in the future change their subordinate IDs again (they have done it once already at least once so they may need to do something similar in the future). When that happens, they will find that all of their --gidmaps may become messed up. And they may not even get an error or a warning... Just wrong IDs being mapped into their containers. Not a nice behaviour in my opinion.

and it is the same mapping done by unshare -r --map-auto.

I haven't verified this (my unshare version is not recent enough) but the docs available at https://man7.org/linux/man-pages/man1/unshare.1.html state that (bold is mine)

  --map-auto
      Map the **first block** of user IDs owned by the effective user
      from /etc/subuid to a block starting at user ID 0. In the
      same manner, also map the **first block** of group IDs owned by
      the effective group from /etc/subgid to a block starting at
      group ID 0. This option is intended to handle the common case
      where the first block of subordinate user and group IDs can
      map the whole user and group ID space. This option is
      equivalent to specifying --map-users=auto and
      --map-groups=auto.

If that is true, then unshare -r --map-auto will map the current user to root and the first block of GIDs to low GIDs, but it will not map other subordinate id blocks, such as my additionally delegated group.

So podman's behaviour of mapping all subordinate blocks and not just the first one is actually different from the one of unshare. I'm starting to think that the current behaviour is actually buggy and not a feature. And if it's a bug then it may be worth fixing it, even if it changes behaviour...

Maybe I would be more convincing if I went to util-linux and convinced the unshare developers of providing an option to map "subordinate blocks different than the first one" to "predictable high IDs" as I am suggesting here? If raising this issue there helps I am willing to go for it.

We usually need to have a root inside the user namespace because otherwise all the files from the image owned by root will show up as owned by nobody.

Yes, that's perfectly fine. No plans to change that. I don't understand why anyone would want to change that. Maybe I did not explain something well.

I suggest you take a look at the --userns=nomap that won't map your user inside the container

I want my user mapped inside the container as root. I want additional groups in the host mapped inside the container to predictable IDs, and that's something podman does not seem to be able to do by default since the mapping and the gidmap I have to provide depend on which groups I have subordinated to my user.

@giuseppe
Copy link
Member

If that is true, then unshare -r --map-auto will map the current user to root and the first block of GIDs to low GIDs, but it will not map other subordinate id blocks, such as my additionally delegated group.

So podman's behaviour of mapping all subordinate blocks and not just the first one is actually different from the one of unshare. I'm starting to think that the current behaviour is actually buggy and not a feature. And if it's a bug then it may be worth fixing it, even if it changes behaviour...

I've used unshare only as an example. Podman does also another thing, it currently sorts the entries, so it doesn't follow the same order as specified in the /etc/subuid and /etc/subgid files.

I don't think the current behavior is buggy, it is just accommodating the most common case. Usually, additional IDs are added when the user realized there are not enough IDs available, so the most common case is to use them all contiguously so that we can pull and deal with images having higher IDs. e.g. I expect that the following add all the listed IDs, not that the second line means mapping 165536 to 165536.

foo:100000:65536
foo:165536:65536

so I am against treating the additional entries with a different meaning.

We could think of adding a function like --uidmap 0:@1000:1000 where the 1000 in @1000 is looked up in the parent user namespace instead of using the current one, but I don't think we should aim for predictable mappings just to make simpler this very specific use case.

@zeehio
Copy link
Contributor Author

zeehio commented Apr 26, 2023

We could think of adding a function like --uidmap 0:@1000:1000 where the 1000 in @1000 is looked up in the parent user namespace instead of using the current one, but I don't think we should aim for predictable mappings just to make simpler this very specific use case.

This would make things simpler and the syntax is straightforward to understand. I like it a lot.

I have also noticed that when I provide a --gidmap I have to provide the full mapping (see the three --gidmap and the --uidmap as well) instead of "extending" the default mapping. Do you know if it would be possible to use something like --append-gidmap to avoid specifying the other mappings?

So instead of:

podman run \
  --rm \
  -v /tmp/test1:/workdir \
  --uidmap "0:0:65535" \
  --gidmap "0:0:1" \
  --gidmap "100000:1:1" \
  --gidmap "1:2:65534" \
  alpine ls -lisan /workdir

I can use:

podman run \
  --rm \
  -v /tmp/test1:/workdir \
  --append-gidmap "100000:@1001:1" \
  alpine ls -lisan /workdir

This would make group mapping in rootless containers much easier to use and understand for many people in my environment.

I don't know if I will be capable of implementing this in a pull request, but if we agree on the design then we can see how to implement it.

Thanks for all the time you are spending on this.

@giuseppe
Copy link
Member

there are no default mappings added when you specify --uidmap (or --gidmap). What would be your expectation when you do something like --append-gidmap "100000:@1001:1"? What should the final mapping be?

@zeehio
Copy link
Contributor Author

zeehio commented Apr 26, 2023

I would expect this command:

podman run \
  --rm \
  --append-gidmap "100000:1:1" \
  alpine

To behave like this:

podman run \
  --rm \
  --uidmap "0:0:65535" \
  --gidmap "0:0:1" \
  --gidmap "100000:1:1" \
  --gidmap "1:2:65534" \
  alpine

When there is no --uidmap and no --gidmap specified podman has a default mapping. I like that default mapping but I want to make just one change to it (e.g. mapping intermediate GID 1 to container GID 100000).

Currently, if I use --gidmap 100000:1:1 I must also specify (1) the identity for --uidmap (0:0:65535) (2) a mapping for gid 0 to my gid --gidmap 0:0:1 and (3) all the other container GIDs to "the rest of my subordinate GIDs" (excluding intermediate GID 1).

@giuseppe
Copy link
Member

this could probably also be expressed using some special annotation for the --gidmap command, e.g.

 --gidmap ">100000:1:1" 

to insert that mapping and break the existing mappings (if any)

@zeehio
Copy link
Contributor Author

zeehio commented Apr 27, 2023

Being able to use

--gidmap ">100000:@1001:1"

When running a container would make a whole community around me (and myself) really happy.

In summary, the features proposed after this discussion are two extensions to the --uidmap and --gidmap mapping syntax. The current syntax mapping is container_id:intermediate_id:map_length.

  • If intermediate_id is of the form @<number>, then <number> is interpreted as the id of the parent namespace.
  • If the mapping starts with a >, then the mapping is meant to be inserted and breaking existing mappings (if any).

I don't know if I will be able to implement these two things, but if nobody else has the bandwidth to do it I suppose that it's either me doing this or letting this linger. I don't have experience with go, but I have been able to follow instructions and build podman myself, so that's a start. I believe I may need to modify the containers/storage repository, since that's where I believe the parsing of id mappings happens. I'm feeling however this may be quite daunting as a first issue for me so your help (or anyone with more experience or time) taking over would make things easier, I guess. Advice and suggestions are very much welcome.

@zeehio
Copy link
Contributor Author

zeehio commented Apr 28, 2023

I'll go step by step, so I will start by exploring the @<id> syntax.

Supporting @<id> in user/group mappings:

To implement support for @<id> I guess I can leverage GetAvailableIDMaps()to get the host->intermediate ID mappings from /proc/self/*id_map.

I should pass those "parent mappings" to the parsing function, and edit the parsing function so when it finds the @ symbol it finds the corresponding parent mapping and replaces the @1001 with whatever the parent mapping is pointing 1001 to.

I believe the parsing function being called is ParseIDMapping() that after some calls ends up calling ParseIDMapFilter.

If I try to grep for ParseIDMapping in containers/podman source code I see a bit more than 20 entries, scattered in several files. I am not familiar with them to tell precisely which of them need to be modified to support this.

Besides, I believe I'd need to change the containers/storage repository to accept the parent mappings as an optional extra argument and to change the parsing so it accepts the @ notation. Apparently the actual parsing is at opencontainers/runc,libcontainer/user/user.go so changes may be needed there as well.

I'm barely capable of doing anything in go, so I am far from knowing precisely if that's the way to go, or if I should just copy some functions from runc into storage and modify them here locally, since this notation seems to be podman specific, rather than spanning all of runc...

I am a bit lost, so getting help here would be very much appreciated.

@rhatdan
Copy link
Member

rhatdan commented Apr 28, 2023

Use the + sign. We have presedent for the - sign already.

--gidmap "+100000:@1001:1"

eitsupi added a commit to rocker-org/website that referenced this issue May 13, 2023
Tagging @cboettig since he suggested me to write something here

I have a solution for running the container rootless:

- rocker-org/rocker-versioned2#636

There are many advantages on rootless containers, the main one being
security.

The main caveat with rootless containers is when we want to map
additional groups to the container (for instance when we have an
additional group that owns a "shared_data" directory we want to access).
In that case, we still need to learn quite a bit about id mapping. I've
done my best to explain how things work and to provide a step by step
guide in this pull request.

Hopefully this will eventually be simplified. It may be that I have
overlooked something

- containers/podman#18333

I guess we can wait some days to see how the issue evolves. It may be
that I've missed something and my solution is overly complicated or that
some feature needs to land in podman to simplify additional group
management.

English is not my primary language. I would appreciate feedback or
change in wordings.

Besides I've been writing this for too long. I may need to take some
time to get some perspective and re-read it again, but I believe it is
worth a first read.

---------

Co-authored-by: eitsupi <[email protected]>
@zeehio
Copy link
Contributor Author

zeehio commented May 27, 2023

I managed to provide an implementation at #18713. It lacks unit testing and documentation, because I have to figure out where do they go.

Comments and feedback are very welcome.

zeehio added a commit to zeehio/podman that referenced this issue Jun 5, 2023
This topic has been discussed at length at containers#18333, with
@giuseppe, @Luap99 and with the feedback from @rhatdan. The requirements were defined there and
this aims to be the implementation.

Motivation
===========

These series of patches aim to make --uidmap and --gidmap easier to use, especially in rootless podman setups.

(I will focus here on the --gidmap option, although the same applies for --uidmap.)

In rootless podman, the user namespace mapping happens in two steps, through an intermediate mapping.

See https://docs.podman.io/en/latest/markdown/podman-run.1.html#uidmap-container-uid-from-uid-amount
for further detail, here is a summary:

First the user GID is mapped to 0 (root), and all subordinate GIDs (defined at /etc/subgid, and
usually >100000) are mapped starting at 1.

If we want to change it further, we can use the --gidmap option, to map that intermediate mapping
to the final mapping that will be seen by the container.

As an example, let's say we have as main GID the group 1000, and we also belong to the additional GID 2000,
that we want to make accessible inside the container.

We first ask the sysadmin to subordinate the group to us, by adding "$user:2000:1" to /etc/subgid.

Then we need to use --gidmap to specify that we want to map GID 2000 into some GID inside the container.

And here is the first trouble:

Since the --gidmap option operates on the intermediate mapping, we first need to figure out where has
podman placed our GID 2000 in that intermediate mapping using:

    podman unshare cat /proc/self/gid_map

Then, we may see that GID 2000 was mapped intermediate GID 5. So our --gidmap option should include:

    --gidmap 20000:5:1

This intermediate mapping may change in the future if further groups are subordinated to us (or we stop
having its subordination), so we are forced to verify the mapping with
`podman unshare cat /proc/self/gid_map` every time, and parse it if we want to script it.

**The first usability improvement** we agreed on containers#18333 is to be able to use:

    --gidmap 20000:@2000:1

so podman does this lookup in the parent user namespace for us.

But this is only part of the problem. We must specify a full gidmap and not only what we want:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1

This is becoming complicated. We had to break the gidmap at 5, because the intermediate 5 had to
be mapped to another value (20000), and then we had to keep mapping all other subordinate ids... up to
close to the maximum number of subordinate ids that we have (or some reasonable value). This is hard
to explain to someone who does not understand how the mappings work internally.

**The second usability improvement** is to be able to use:

   --gidmap "+20000:@2000:1"

where the plus sign (`+`) states that we want to start with an identity mapping, and break it where
necessary so this mapping gets included.

One final improvement related to this is the following:

By default, when podman  gets a --gidmap argument but not a --uidmap argument, it copies the mapping.
With the new syntax this copying does not make sense. Having a GID subordinated to us does not imply
that the same UID will be subordinated as well. This means, that when we wanted to use:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1

We also had to include:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1 --uidmap 0:0:65000

making everything even harder to understand without proper context.

In this series of patches, when a "break and insert" gidmap is given (using the described `+` syntax)
without a --uidmap, we assume that we want the "identity mapping" as --uidmap (0:0:65000).

To preserve backwards compatibility, this different default mapping is only used when the `+` syntax
is used, so users who rely on the previous behaviour don't suffer any changes.

Signed-off-by: Sergio Oller <[email protected]>
@github-actions
Copy link

A friendly reminder that this issue had no activity for 30 days.

@zeehio
Copy link
Contributor Author

zeehio commented Jun 27, 2023

Thanks bot. I have been busy with work but I haven't forgotten this, I just need a bit more time

@github-actions
Copy link

A friendly reminder that this issue had no activity for 30 days.

@rhatdan
Copy link
Member

rhatdan commented Aug 16, 2023

@zeehio Reminder.

zeehio added a commit to zeehio/podman that referenced this issue Aug 28, 2023
Motivation
===========

This feature aims to make --uidmap and --gidmap easier to use, especially in rootless podman setups.

(I will focus here on the --gidmap option, although the same applies for --uidmap.)

In rootless podman, the user namespace mapping happens in two steps, through an intermediate mapping.

See https://docs.podman.io/en/latest/markdown/podman-run.1.html#uidmap-container-uid-from-uid-amount
for further detail, here is a summary:

First the user GID is mapped to 0 (root), and all subordinate GIDs (defined at /etc/subgid, and
usually >100000) are mapped starting at 1.

One way to customize the mapping is through the `--gidmap` option, that maps that intermediate mapping
to the final mapping that will be seen by the container.

As an example, let's say we have as main GID the group 1000, and we also belong to the additional GID 2000,
that we want to make accessible inside the container.

We first ask the sysadmin to subordinate the group to us, by adding "$user:2000:1" to /etc/subgid.

Then we need to use --gidmap to specify that we want to map GID 2000 into some GID inside the container.

And here is the first trouble:

Since the --gidmap option operates on the intermediate mapping, we first need to figure out where has
podman placed our GID 2000 in that intermediate mapping using:

    podman unshare cat /proc/self/gid_map

Then, we may see that GID 2000 was mapped to intermediate GID 5. So our --gidmap option should include:

    --gidmap 20000:5:1

This intermediate mapping may change in the future if further groups are subordinated to us (or we stop
having its subordination), so we are forced to verify the mapping with
`podman unshare cat /proc/self/gid_map` every time, and parse it if we want to script it.

**The first usability improvement** we agreed on containers#18333 is to be able to use:

    --gidmap 20000:@2000:1

so podman does this lookup in the parent user namespace for us.

But this is only part of the problem. We must specify a **full** gidmap and not only what we want:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1

This is becoming complicated. We had to break the gidmap at 5, because the intermediate 5 had to
be mapped to another value (20000), and then we had to keep mapping all other subordinate ids... up to
close to the maximum number of subordinate ids that we have (or some reasonable value). This is hard
to explain to someone who does not understand how the mappings work internally.

To simplify this, **the second usability improvement** is to be able to use:

   --gidmap "+20000:@2000:1"

where the plus flag (`+`) states that the given mapping should extend any previous/default mapping,
overriding any previous conflicting assignment.

Podman will set that mapping and fill the rest of mapped gids with all other subordinated gids, leading
to the same (or an equivalent) full gidmap that we were specifying before.

One final usability improvement related to this is the following:

By default, when podman  gets a --gidmap argument but not a --uidmap argument, it copies the mapping.
This is convenient in many scenarios, since usually subordinated uids and gids are assigned in chunks
simultaneously, and the subordinated IDs in /etc/subuid and /etc/subgid for a given user match.

For scenarios with additional subordinated GIDs, this map copying is annoying, since it forces the user
to provide a --uidmap, to prevent the copy from being made. This means, that when the user wants:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1

The user has to include a uidmap as well:

    --gidmap 0:0:5 --gidmap 5:6:15000 --gidmap 20000:5:1 --uidmap 0:0:65000

making everything even harder to understand without proper context.

For this reason, besides the "+" flag, we introduce the "u" and "g" flags. Those flags applied to a
mapping tell podman that the mapping should only apply to users or groups, and ignored otherwise.

Therefore we can use:

   --gidmap "+g20000:@2000:1"

So the mapping only applies to groups and is ignored for uidmaps. If no "u" nor "g" flag is assigned
podman assumes the mapping applies to both users and groups as before, so we preserve backwards compatibility.

Co-authored-by: Tom Sweeney <[email protected]>
Signed-off-by: Sergio Oller <[email protected]>
@github-actions github-actions bot added the locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments. label Nov 29, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/feature Categorizes issue or PR as related to a new feature. locked - please file new issue/PR Assist humans wanting to comment on an old issue or PR with locked comments.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants