owncloud / product

ownCloud Product Backlog
GNU Lesser General Public License v3.0
0 stars 1 forks source link

ocis-accounts service #73

Open butonic opened 4 years ago

butonic commented 4 years ago

We need to use the ocis-accounts service as the user backend. It contains normal users and guest accounts that we want to make accessible using LDAP so that kopano can access them.

Tasks

ocis-glauth tasks @butonic

ocis-accounts Tasks

ocis-proxy steps (order is important) @refs @IljaN

ocis-pkg

ocis-settings Tasks @kulmann

Other

Estimation

micbar commented 4 years ago

Feedback from reviews:

@michaelstingl

butonic commented 4 years ago

A problem I ran into, which requires additional design.

We need to deal out unique uidnumbers but the graph api has no property for them. So I currently, cannot, without bendingf the rules use the graph api as the backend for glauth. We are using glauth as an ldap server to provide posixaccounts to eos. a posixaccount MUST have the cn, uid, uidNumber, gidNumber, and homeDirectory attributes.

Furthermore, if we are effectively provisioning the accounts, we may need to use a specific uid range to prevent collisions with existing users in other ldap domains. See Red Hat Enterprise Linux > 6 > Identity Management Guide > 9.9. Managing Unique UID and GID Number Assignments for some background. Also we should skip some uidNumbers when looking at UID, GID, SID and RID ... who are you. which deals with mixing ids from ldap and windows. It seems to be recommended to start over 65535 to prevent collisions with local uids.

In the OS the uidNumber becomes the numeric uid, uid (userid) becomes the username or login id and cn is the common name or display name.

The questions are:

butonic commented 4 years ago

There are two scenarios where we need an ldap server:

  1. the storage should integrate the accounts to allow bypassing ocis/reva, eg using ssh. In that case the uidNumbers must be unique across internal and guest accounts.
  2. the firewall should check if a guest exists before allowing the request to pass into the dmz

We could request an ldap server or credentials with write permissions for these scenarios if the guest provisioning algorithm from owncloud should be used. If another process for guest accounts exists we can assume the uidnumber to be conflict free, the storage can bo configured to use the existing ldap server.

But what if uidnumbers collide in case of a merger?

The other option is to always manage accounts ourself, which is what we do with the accounts service and provide an ldap interface for the customer so he can use it to integrate the storage and firewall.

But can and do we want to implement a scalable ldap server?

Putting users into the filesystem to let eg eos georeplicate the users for the storage makes sense.

Conlusion

if we use acis-accounts as the source of truth, the merge problem remains the same. We could apply same uidnumber range strategy as in Red Hat Enterprise Linux > 6 > Identity Management Guide > 9.9. Managing Unique UID and GID Number Assignments

butonic commented 4 years ago

ocis-accounts only exists to generate a uuid for users. we look up the sub@iss in the accounts service and generate a uuid if necessary.

technically, this can be replaced with a lookup of the user in an ldap server by email or username, whatever claim is sent by the oidc provider. might be a userPrincipalName or a guid. MS has the same problem for their Azure AD / graph: https://docs.microsoft.com/en-us/azure/active-directory/hybrid/plan-connect-design-concepts

The sourceAnchor is used to link existing objects in Azure AD with objects on-premises. IT is also called immutableId and the two names are used interchangeable. It used to default to the objectGUID, but it can change, which is why it now defaults to ms-DS-ConsistencyGuid. ms-DS-ConsistencyGuid defaults to the objectGUID, but it can also take non GUID values aka as byte arrads for legacy compatability.

Which brings us back to the mapping sub@iss to a stable attribute problem.

We need a stable attribute for federated sharing. The id must never change, but it must be mergeable / conflict free when merging two ocis instances. The only type of id that allows that are UUIDs.

Note that this kind of uniqueness is also needed for groups. But there are occasions where millions of groups are in place. And during a migration they might have to be merged. Which leads to the problem of replacing uids and gids in shares and permissions.

This is similar to cross storage moves. The storage id will change ... which will change the fileid. For ocis we plan to drop support for cross storage move and make it a copy and delete operation to notify the user that shares to that file will be removed until we implement a history of old file ids. When the storage providers cooperate we can redirect to the new target and the requesting client can update his reference.

Maybe we can implment something that can deal with changing uids and gids using a history. ms already has a sid history in ad.

butonic commented 4 years ago

currently

  1. during auth the sub@iss is used to look up the uuid in ocis-accounts
  2. the corresponding ldap user is looked up using the email or username
  3. the uidnumber and gidnimber are used to persist acls and file ownership

other approach:

  1. during auth the auuh token is used to look up the email at the idp (or it is in the id token)
  2. the corresponding ldap user is looked up using the email
  3. the uidnumber and gidnimber are used to persist acls and file ownership

changes to the uidnumber and gidnumber must be dealt with by the directory admin. should ocis support changing usernames (chmod) and acls (getfacl -R ... & setfacl --restore=... maybe?)?

The sub@iss won't change unless the idp product changes. oidc knows nothing about groups so we need to talk to an ldap anyway. but ldap has no persistent dentifiers unless we add our own. we could add a schema and copy the current uuid (objectguid or entryuuid or whatever) into that custom attribute. which might still collide when we have to merge two ldap directories.

butonic commented 4 years ago

If we store the sub@iss in cs3 grants we need a way to update them when the sub@iss changes due to a change of the idp product. Or we need to be able to rebuild the shares in the share manager from the storage.

For groups it will be even harder to maintain a uuid ...

we either need an ldap attribute with a uuid value we can use, or we need write access to the ldap server so we can generate the uuid on the fly.

we can define a schema for that attribute.

https://ldapwiki.com/wiki/Best%20Practices%20For%20Unique%20Identifiers

butonic commented 4 years ago

another thing we need for sharing is a way to map the claims in the idtoken / from the userinfo endpoint to an account. when sharing files with others the account might not have been provisioned yet. if we can only share with existing accounts we also need a way to map an email to that account.

to share with other users the email allows starting an oidc discovery to find the issuer for the user. the webfinger protocol allows looking up users: https://openid.net/specs/openid-connect-discovery-1_0.html#AcctURISyntax or https://openid.net/specs/openid-connect-discovery-1_0.html#EmailSyntax

another interesting link: fastfed spec https://openid.net/specs/fastfed-core-1_0-02.html#ScimSchemaGrammar very recent: https://bitbucket.org/openid/fastfed/src/master/

butonic commented 4 years ago

In the end switching the idp is the same as migrating a user.

butonic commented 4 years ago

The first user story is changing the idp due to a merger, or because an external user becomes an internal user or vice versa. In those cases the sub@iss combo will change. But we need a stable identifier for federated shares. ocis-accounts will generate and store the accounts, which consist of the uuid and a set of identities. An identity consists of an issuer, an issuer assigned id and a type. similar to the ms graph objectIdentity resource. This allows adding multiple identities to an account.

With a generated uuid we can identify the users. Instead of generating the id ourself we should use the scim_id or scim_externalid claim if it is present in the oidc id token claims. That spec is still a draft, but scim and oidc are also tied together in the recent OIDC FastFed draft:https://openid.net/specs/fastfed-scim-1_0-02.html

To persist shares as acls we need the current username under which the user is known in the os. For unix this can be done by configuring pamto use ldap to resolve accounts. We could use other modules like pam_mysql or even implement new ones, but the fact that we a numeric uid and a username pair does not change. It is however optional because it is only necessary when trying to persist shares as acls to the filesystem.

When using a fuse overlay the owner user uuid and group uuid could be stored as extended attributes. shares can use an acl like syntax but with the uuid and store that in a dedicated file, because extended attributes are limited in space.

I already mentioned group uuids. Which AFAICT is only needed for federated group shares ...

butonic commented 4 years ago

hm stumbled over https://systemd.io/USER_RECORD/ again.

The oidc claims have a preferred username. we could check if a user with the name exists. either by checking /home/<username>.homedir/.identity or a different path, eg /var/lib/ocis/<username>.homedir/.identity.

that would be lookup by username.

We could cache the identities in glauth to enable searching other properties using ldap. then searching for recipients would have to use ldap to find accounts. or do an oidc discovery by email. a homed backend for glauth. well ... homed is hardcoded to /home ... but we could at least use the USER_RECORD json format ...

butonic commented 4 years ago

glauth with write support and homed backend as a minimal persistence layer for accounts

butonic commented 4 years ago

Scenarios:

no LDAP integration

-> ocis uses ocis-glauth to persist accounts using LDAP -> uuids are generated by accounts service and stored in glauth using LDAP -> posixaccount.numericUid (for os integration) is generated by accounts service and stored in glauth using LDAP -> guests are provisioned by ocis on the fly as users using LDAP

write access to external LDAP

-> same as no LDAP integration -> add LDAP schema for our uuid or configure a suited attribute

read only access to LDAP

-> ocis cannot manage accounts -> uuid must be provided by LDAP (with schema) -> posixaccount.numericuid must be provided by LDAP -> guests must be provisioned by external process

Remarks

We always need to look up users using username, email or our LDAP uuid that is sent by the IdP as an additional claim. sub claim is useless to us because we cannot look up users with it. One exception: no ldap integration, means we manage all the accounts and could use sub as the uuid ... but then we leak the sub, which might be considered ok if it is a Pairwise Pseudonymous Identifier (PPID)

butonic commented 4 years ago

systemd-homed seems to evolve in the direction we need: https://github.com/systemd/systemd/blob/a9ab5cdb505d7d368c44fc02cc0183e75db1f657/docs/USERDB_AND_DESKTOPS.md#future-additions

butonic commented 4 years ago

Handover:

Where are we? Starting with protocol changes in ocis-accounts:

The PR for this is https://github.com/owncloud/ocis-accounts/pull/30

Update depending extensions

Some services need to be updated

Update ocis-glauth to use the glauth:homed branch

Testing:

After adding all the changed repos to your ocis go.mod

replace github.com/owncloud/ocis-accounts => ../ocis-accounts
replace github.com/owncloud/ocis-proxy => ../ocis-proxy
replace github.com/owncloud/ocis-migration => ../ocis-migration
replace github.com/owncloud/ocis-glauth => ../ocis-glauth
replace github.com/glauth/glauth => ../glauth

the only thing that currently works is listing users using the api gateway:

$ curl 'http://localhost:8082/rpc' \                  
  -H 'Content-type: application/json' \
  -H 'Accept: */*' \
  -H 'Origin: http://localhost:8082' \
  -d '{"service":"com.owncloud.api.accounts","endpoint":"AccountsService.ListAccounts","request":{}}'
{"accounts":[{"accountId":"9b02e06a-4ad0-43bd-afe9-2e4fccdc2a0a","username":"reva","mail":"storage@example.org"},{"accountId":"e0b79cfd-fa8c-436b-aca5-0a45fbd9e38c","username":"einstein","mail":"einstein@example.org"}]}

Next steps

exalate-issue-sync[bot] commented 4 years ago

Remote key is https://jira.owncloud.com/browse/OC-1972

butonic commented 4 years ago

next steps

ocis-accounts