ii / infra

2 stars 4 forks source link

Automatically populate certain emails or GitHub org/groups as "authentik Admins" #17

Open hh opened 4 months ago

hh commented 4 months ago

When we login to a new instance, akadmin is the owner member of "authentik Admins" group.

I'd like to automatically add some users to that group automatically based on their GitHub org/group or possible a list of email or domains.

hh commented 4 months ago

Opened an issue with Authentik: image

phorcys420 commented 4 months ago

The GH OAuth source uses the default authentication (existing users) (ii-source-authentication-flow) and source enrollment flows (new users) (ii-source-enrollment-flow), both of those have to be modified in some way to account for the user's GH org or email domain.

I don't think we can do a "store group in a variable and apply it in the next flow" type thing with authentik, but we can do the next best thing which is redirecting the flow to a stage that has the group preconfigured.

Given the condition is binary and only needs to match "is admin?" and doesn't need granular 1 group per-email type thing we could have the following (modeled in JS for understanding) :

if(user.shouldBeAdmin()) {
    adminUserWrite(user); // new "ii-source-enrollment-admin-write" stage
} else {
    userWrite(user); // already-existing "ii-source-enrollment-write" stage
}

In authentik, the conditions are called "policies", we can bind a policy to a stage, meaning we can do what I suggested above on a true/false basis.

For this, an "expression" policy seems to be the best bet, it allows us to run our own Python code inside the policy. See Expression Policies -> Variables for the available variables in the Python context and User properties and attributes -> Object properties for request.user properties.


I could piece a policy together based on the email domain, I think this is the way to go. Using the GH API to get public orgs might slow down the enrollment and auth flows too much, it should be tried still but I don't know if it'll be viable.

adminDomains = ["ii.nz"]
userEmailDomain = request.user.email.split("@")[1]

return userEmailDomain in adminDomains

image

image

hh commented 4 months ago

Thanks for your 👀 on this @phorcys420 !