-
-
Notifications
You must be signed in to change notification settings - Fork 288
How can we keep the uid and gid constant #46
Comments
Brain dump. I think that Proposal 4 has the most 'legs' maybe. But I would keep pondering for a little bit: Well, let's look at what we do have in IAM that's constant. Is it just the ARN? E.g. something like:
If so, that's a good place to start to try and 'generate' our userid? Proposal 1:So I'm thinking something, like, we take the CRC32 of that thing, modulo 'x' it (for some value of 'x' TBD), add an offset to make it not conflict with the built-in /etc/passwd users (probably an offset of 1000 would do?). Problems:
Proposal 2:Well, if we look just at the username - Proposal 3:If there were a consistent way to list IAM users - like, they always show up in the same order - and if they somehow showed a gap for deleted users - we could assign uid's in order? I think the biggest issue here is deleted users; for old servers it would be fine because they would 'know' about the missing user. For new servers, who never knew about the gap, they would try and misnumber Proposal 4:This one is well and truly horrible, but it might be the best bet. We attach a magical, no-permissions, valueless role or permission to each IAM user. Like, maybe an inline policy. Maybe the policy is completely blank. But the name of the policy is something like:
And from there, all servers now know that that IAM user is always to be uid-1003? (And similar with gid?) One note - we'd have to keep track of "last_used_uid" somewhere. Hell, maybe another IAM user, who exists just to be a counter (also has no perms?) - |
I also though about hashing the username (or ARN, doesn't matter in this case) but I'm not aware of a mechanism that does not come with collisions as you mentioned. So I think we need to keep some state somewhere like Proposal 4 suggest. But instead of the IAM user I was thinking of a DynamoDB table or something. There we could easily keep track of users and their assigned uid / gid. But it makes the whole thing more complicated to setup... |
I have also been thinking about this. There is nothing really usable in IAM. hashing the names will be a problem, as it's too easy to have collisions. The best thing would be tags, but AWS did not implement tags for IAM users :( So I could only think of:
All of this sounds like a lot of extra complexity, and if we go implement this I would strongly opt for making it optional, disabled by default. I only had to handle this once (our jenkins machines use efs for storage. I ended up picking a uid for the jenkins user and put this uid in the userdata, and only fix the uid for the jenkins user) Maybe we can open a feature request with AWS to allow tags on IAM users? ;-) |
I'm a fan of keeping things simple. This project started as a few lines of bash :) |
I agree :) |
That's where I'm leaning currently too. But it's still something we should think about; consistent uid/gid's would enable things like NFS/EFS, and there are some people out there who might think that's a big deal. I did an experiment with a simple 'inline policy' - {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1494299234000",
"Effect": "Allow",
"Action": [
"ec2:DescribeAvailabilityZones"
],
"Resource": [
"*"
]
}
]
} (that just allows you to list ec2 availability zones, but any simple, near-empty or meaningless policy would work). I then attached this inline to my user using the console. Finally, I was able to do this:
I honestly don't think it's too awful? Hrm? |
The only concern I have is that the AWS API is eventual consistent. Which means that you can not use the API to assign unique values. |
That would only be a problem right after adding this inline policy right? My main concern is: how do we handle a mix? Some users have this policy, others dont. It also adds a lot of api calls which means less users/instances can be managed this way. Tricky feature. |
Yeah, and to the earliest point, it might not be worth it to do at all. But let's at least keep stepping through it. (oh, and for people who don't have the policy, when the update-users script fires, it would start assigning them in order). The eventual consistency issue is definitely still an issue, but only at the moment where you are trying to assign a new uid. Once it's assigned, it's pretty painless on currently-existing servers as well as brand new ones - you just use it to set the uid, that's it. But if you have 'n' servers, and their cronjobs all fire at the same time - chances of some kind of conflict are definitely there. I think some of this is mitigated iff the user-listing we get back from IAM keeps the same order; so long as we keep appending new UID's in order to that, then even if two people try to do it at the same time, it might be OK? Would we still need some kind of 'marker' (fake IAM user?) so that you don't inadvertently re-use the last issued uid, or is that not an issue? E.g. if you have uid 1001, 1002, 1003, and delete 1002, that's easy, next one is 1004. But if, instead, you deleted 1003, wouldn't you end up trying to re-use 1003? Is that bad? If eventual consistency is an issue, we might be able to use the So I still think it's doable, and I think it'd even probably work, but I worry that if we try and go this way, we'll end up having to build a full identity-provider á la LDAP or something, and deal with nssswitch and/or a whole bunch of other craziness. Though, to be fair, we already do interact with PAM, so maybe that's not the worst thing ever....oh, I dunno. Anyways, just wanted to at least try and think the idea through to its logical conclusion. |
Just a question (You may have already thought about this), but why not use the
Amazon's IAM documentation also says that it would make sense to use that It would seem that all that would be needed is to change the EDIT: I think that going to some type of "Create a persistent mapping object for lookups to be done" is a bit stretching the scope of this project. If that's something that is needed for a Linux cluster, you are likely better served by implementing an LDAP solution and tying PAM into that to do username lookups. That would guarantee that you have the advantage of stable UIDs and GIDs, and would be far more robust than trying to tack on a lookup solution here. It would also scale way beyond (in terms of number of users) what would likely be the expected use case for doing a direct IAM sync using the AWS CLI tools. I would think this project is geared towards smaller use cases (about a few hundred users at the most, and please correct me if I am mistaken), so it's more a question of picking a hash function which has a collision probability curve that remains low enough through about 250 or so users. |
Maybe we should find out what's the largest uid for Amazon Linux. According to https://en.wikipedia.org/wiki/User_identifier#Type this could be a bit tricky because there seem to be reserved numbers and stuff. I could check the The Linux Programming Interface book to see if there is something in there. Or maybe we find someone who nows about uids in Amazon Linux? |
My recollection is that UID space from kernel 2.4 onwards is unsigned 32 bit integers. If we shift the result up by about 2000, that should cover system accounts and packaged application accounts. The only gotcha is the UID for I'll check the max UID and report back here. |
Looks like the maximum is 2^32 - 2 (4294967294). My suspicion is that 2^32 - 1 is reserved for 'Invalid UID', but again, that's something that we can test for.
User
At least on Amazon Linux, it looks like we start at 500 and then go upwards from there. That's in So as long as the digesting of the IAM UserId field puts us between about 2000 (I think that's enough safety margin) and 2^32-2 as possible values. I would think that would be a large enough field for small user groups that are natively on IAM to fit in without a high risk of collision. |
Ooh - here's a kinda nutty idea - What if we use the creation time to generate the uid? We could set the 0-date as 1/1/2000 for simplicity's sake. (pardon the fuzziness of the numbers, I'm doing this with a shitty calculator and not using proper date math) - The minimum possible user ID you could ever get would be from around the creation of AWS (probably later; the creation of IAM) - call that 1/1/2006 for the sake of argument - I think that translates to something like 189,000,000 which is well within 32 bits, and well above the minimal user ID that might cause collisions. Then we burn around 31 million uid's per year until we exhaust the 32-bit address space. Another interesting side-effect - newer users get higher user-id's. That's kinda neat. The only drawback? You can't create two IAM users at the same exact second, or else they'll get the same UID. We could probably pretty easily see that inside the IAM user listing and issue an error if we caught that. The fix would be "Delete one of those IAM users and re-create it". Of course, if you're using a hardcore enough number of IAM users then you might start to find this a problem - but if you are you're probably going to want to use LDAP instead, anyways. The crazy thing is this actually could work, and solves a lot of problems. Eventual consistency? Doesn't matter! Whenever your user eventually shows up, so long as they were created at a unique timestamp, then that's their This seems completely psychotic to me, but I can't seem to figure out what might break it, unless I'm severely botching my math. But, I guess....I mean, the Unix Epoch problem isn't expected to reach criticality until 2038 - and if we start at 2000 instead of 1970, we get an extra 30 years anyways! (And if we really wanted to, we could use straight-Unix-epoch timestamps - those won't exhaust the 32-bit address space until 2038 and that's plenty of time :p ) Honestly this seems like it actually could work. Wow, that's really nuts. What do you folks think? |
Technically you could use a UNIX timestamp where time_t is signed 64 bits long (You're going to truncate it anyway to unsigned 32 bit int by dropping the upper 32 bits...32-bit time_t was a signed 32 bit int, so that's the origin of the 2038 problem, unsigned 32-bit int time_t would be good until 2106), you adjust by the creation of IAM UNIX timestamp (If you want), adjust for system accounts and So yeah, that could theoretically work. Also just thinking out loud... In the case of using Elastic File System for mounting user home directories, this would also be dependent upon Amazon's NFSv4 Server (and the NFS Utilities on the EC2 instances) dealing with unsigned 32-bit UIDs and GIDs correctly. I don't have direct knowledge that those things have been thought of in the implementation of EFS. Are there any other pieces of software that are in common use that depend that heavily on UIDs that would have issues with 32 bit UIDs? I don't know of any offhand... For what it's worth...I'm managing a set of basically 20 users, half of which are various service accounts for apps that don't handle EC2 Instance IAM Profiles correctly. If I got a 32-bit hash collision on the IAM UserId fields on the accounts for the 10 actual people, I'd probably go out and buy a lottery ticket... (If it was 100 users, I'd go run around a golf course with a 4 iron in my hand during a lightning storm. More than that? I think I'd be smart enough to be using LDAP...) |
Why didn't I think of that! Pretty smart idea there. We should try this. It can be implemented in a brach and tested with several of the services (specially EFS of course). I like the idea, I really do. |
Hey it took me 7 months to come up with it myself!!! |
My only thoughts: I would prefer hashing the uid/arn (unique value) to an unsigned integer instead of the creation date where we don't have any guarantees on uniqueness. In case of an uid collision we should log this as we do at the moment with usernames > 32 characters. |
I have a preference to the hash into unsigned 32 bit integer space as well, mainly due to the fact that I'm unsure about how IAM deals with users federated into IAM and their create dates (and I don't have a way to test that functionality. Is it date when they were actually created or when they first federated?) But that may be worrying about things beyond the scope here. |
As per the linked PR above I suggest to speed up the login of the users out of the scope of the sync, to establish which user is from IAM, and which one is not, the sync script already use groups, namely |
The only place I see the fast fail PR, well, failing, is where the users are being created by something other than the bundled At present, this codebase doesn't guarantee a stable UID for IAM users, simply because there isn't a GUID that can be quickly hashed with low collision probability into Linux UID space. The OS itself uses unsigned 32 bit integers nowadays, but there's always the question of legacy software that expects UIDs to be shorter. So once this question here is decided, then that would likely guide how we handle users that are not in IAM. |
I don't feel too strongly, about sticking with just creation date, but I think I can lay out my arguments at least -
Let me do some test |
Here's a little PHP script I whipped up to help play with some of these numbers - feel free to give it a whirl. <?php
$results=`AWS_PROFILE=production aws iam list-users`;
$ans=json_decode($results);
//print_r($ans);
foreach($ans->Users AS $user) {
//print "User is: ";
//print_r($user);
$username=$user->UserName;
$userid=$user->UserId;
$arn=$user->Arn;
$createdate=$user->CreateDate;
print "User: $username hashes: ".crc32($username).", ".crc32($userid).", ".crc32($arn).", ".strtotime($createdate)."\n";
} |
the keymaker project attempts to solve this issue by grabbing the UserId from IAM and converting it to an int.. |
Since the latest link is outdated: https://github.com/kislyuk/keymaker/blob/721d3c0894a8c216e8b681afc26d043e9a0975a8/keymaker/__init__.py#L166-L172 |
I'm not sure if something similar is possible in plain bash. But we could also use some python for that. Because aws cli depends on python. So we have python as a dependency already :) |
It looks like you can 'tag' users now in IAM. That'd probably be a pretty good way to give them unique uid's? The only thing you have to, kinda, worry about would be making sure you can carefully number them and not have conflicting |
We do not guarantee constant uid and gid for created local users at the moment. How could we handle this?
The text was updated successfully, but these errors were encountered: