For containerized environments it is helpful to enable centrally-managed allocation and distribution of ID sub-ranges for users/groups to use in podman and runc.
As discussed in https://github.com/shadow-maint/shadow/issues/154, https://github.com/shadow-maint/shadow/commit/0a7888b1fad613a052b988b01a71933b67296e68 adds a new interface, libsubid. This interface will be extended to allow pluggable backends.
The purpose of this ticket is to track two tasks: - add support for storing per-user/group subid ranges in FreeIPA - track retrieval and distribution of per-user/group subid ranges in SSSD
For the latter a new ticket needs to be added.
SSSD ticket: https://github.com/SSSD/sssd/issues/5197
Metadata Update from @cheimes: - Issue assigned to cheimes
Metadata Update from @cheimes: - Issue priority set to: important - Issue set to the milestone: FreeIPA 4.9 - Issue tagged with: rfe
Each entry of /etc/subuid and /etc/subgid has three fields:
The numerical id is the start value of an invertal. The count specifies to size of the interval. A typical value for a count is 65536. An implementation should ensure that intervals don't overlap or conflict with reserved ranges for standard uidNumber and gidNumber. 389-DS LDAP server has a distributed numeric assignment plugin (DNA) that takes care of assigning numbers in a master-master replication. The DNA plugin does not support intervals, the feature is disabled.
65536
uidNumber
gidNumber
subuid and subgid have a 1:1 relationship to users. Therefore it makes sense to store both mappings directly in user entries. The feature requires one auxiliar object classes with four mandatory integer field for start number and count: subuidNumber, subuidCount, subgidNumber, subgidCount. IMHO it does not make much sense to have subuid without subgid.
subuidNumber
subuidCount
subgidNumber
subgidCount
The maximum value for user and group ids are restricted. uid_t and gid_t are aliases for unsigned int (uint32_t). I assume that subuid and subgid are restricted to 32 bit unsigned ints as well. With idstart = random.randint(1, 10000) * 200000 and count = 65536 IPA would support about 35,000 users with subuid/subgid ranges. It looks like 65536 is actually required to properly map nobody to uid=65534.
uid_t
gid_t
uint32_t
idstart = random.randint(1, 10000) * 200000
count = 65536
nobody
uid=65534
>>> subuid_count = 65536 >>> uid_max = 1 << 32 >>> ipa_idstart_max = 10000 * 200000 >>> ipa_idmax = ipa_idstart_max + 200000 - 1 >>> (uid_max - ipa_idmax) // subuid_count 35015
To simplify the implementation it may make sense to hardcode the count value and set subuidNumber == subgidNumber. I think we could even go so far and derive the subuidNumber from uidNumber so we don't have to worry about overlapping ranges.
subuidNumber == subgidNumber
subuidnumber = subuid_start + (uidnumber - idstart) * subuid_count
The assignment could be handled by a 389-DS plugin.
Question: Is the range a 32bit, 64bit, or machine dependent integer? shadowutils defines the range values as unsigned long, see idmapping.h, but have_sub_uids() uses uid_t as start value.
unsigned long
Metadata Update from @cheimes: - Custom field on_review adjusted to https://github.com/freeipa/freeipa/pull/5438
Hi @cheimes ,
do I understand your proposal correctly that subuid_start == (ipa_idmax + 1)?
subuid_start
ipa_idmax + 1
While I like the simplicity of the approach, I have a few questions:
1) what would be subuidnumber for users with (uidnumber - idstart) > 35015? Will we disallow/disable sub-id ranges for those users? IIUC, this should be very common case for example when replica requests own range and 200k are split.
subuidnumber
(uidnumber - idstart) > 35015
2) I'm not sure I understand Adding New Ranges correctly, but looks like initial 200k range can be extended manually? I guess, this operation at least changes idstart and thus either invalidates existing assignments or creates potential for conflicts?
idstart
3) The same doc mentions: "if two separate FreeIPA domains are ever merged in the future". In this case we will get overlapping sub-id ranges?
4) Is it required to take into account AD trust ranges when IPA generates IDs for AD users? (I don't know what ID space is used for this...)
5) In case of trust with AD that defines and populates own attrs for sub-id ranges, will we ignore those?
After further investigation I came to the conclusion that this approach is not going to work:
[idstart, idmax]
ipa user-add
uidNumber=idstart + 100000
Back to the drawing board!
It looks like 65536 is actually required to properly map nobody to uid=65534.
If I read man newuidmap correctly (please correct me if I'm wrong), nothing prevents calling newuidmap $pid 65534 anything_in_the_allowed_interval 1 and thus mapping of 65534 doesn't necessary require interval size >= 65536, right?
man newuidmap
newuidmap $pid 65534 anything_in_the_allowed_interval 1
Hi @cheimes , It looks like 65536 is actually required to properly map nobody to uid=65534. If I read man newuidmap correctly (please correct me if I'm wrong), nothing prevents calling newuidmap $pid 65534 anything_in_the_allowed_interval 1 and thus mapping of 65534 doesn't necessary require interval size >= 65536, right?
No, despite this is technically possible, this is not what Podman uses...
Metadata Update from @cheimes: - Custom field on_review adjusted to https://github.com/freeipa/freeipa/pull/5652 (was: https://github.com/freeipa/freeipa/pull/5438)
master:
ipa-4-9:
Metadata Update from @rcritten: - Issue close_status updated to: fixed - Issue status updated to: Closed (was: Open)
Metadata Update from @frenaud: - Custom field changelog adjusted to IPA is now able to centrally store ID sub-ranges for users/groups. More details can be found in the design document: https://freeipa.readthedocs.io/en/latest/designs/subordinate-ids.html
Login to comment on this ticket.