diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index c83dc398cb..def94de547 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -66,8 +66,10 @@ - [Design Documents]() - [Access Profiles 2022](developers/designs/access_profiles_rework_2022.md) - [Access Profiles Original](developers/designs/access_profiles_and_security.md) + - [Access Control Defaults](developers/designs/access_control_defaults.md) - [Architecture](developers/designs/architecture.md) - [Authentication flow](developers/designs/authentication_flow.md) + - [Domain Join](developers/designs/domain_join.md) - [Elevated Priv Mode](developers/designs/elevated_priv_mode.md) - [Oauth2 Refresh Tokens](developers/designs/oauth2_refresh_tokens.md) - [Replication Coordinator](developers/designs/replication_coord.md) diff --git a/book/src/developers/designs/access_control_defaults.md b/book/src/developers/designs/access_control_defaults.md new file mode 100644 index 0000000000..bc9881d578 --- /dev/null +++ b/book/src/developers/designs/access_control_defaults.md @@ -0,0 +1,162 @@ +# Access Control Defaults + +- Do we need some kind of permission atoms to allow certain tasks? + +## Use Cases: + +- User sign-up portal (need service account that can create users and do cred reset) +- Role for service account generation. +- Remote backup - this account should be able to trigger and retrieve a backup +- Groups should be able to be changed by a managing group (managed by) +- IP limits on accounts? + +- Users need to not be able to see other users. + - Means the user can't read member attr, but can see groups + group info. + +- Anonymous needs to be able to be blocked more easily. +- Enable disable self-mail write +- Enable disable self-name-change + +## To achieve + +- IP access limits +- Managed By rules +- Better group specification syntax (not filters) + +## Domain Admin + +```mermaid +graph LR + +DomainAdmin("Domain Admin") --> AccessControlAdmin("Access Control Admin") +DomainAdmin("Domain Admin") --> AccountPolicyAdmin("Account Policy Admin") +DomainAdmin("Domain Admin") --> DomainConfigAdmin("Domain Config Admin") +DomainAdmin("Domain Admin") --> HPGroupAdmin("HP Group Admin") +DomainAdmin("Domain Admin") --> SchemaAdmin("Schema Admin") +DomainAdmin("Domain Admin") --> SyncAccountAdmin("Sync Account Admin") +``` + +## IDM Admin + +```mermaid +graph LR + +IdmAdmin("IDM Admin") --> GroupAdmin("Group Admin") +IdmAdmin("IDM Admin") --> PersonAdmin("Person Admin") +IdmAdmin("IDM Admin") --> PersonPIIModify("Person PII Modify") +IdmAdmin("IDM Admin") --> PersonReadNoPII("Person Read No PII") +IdmAdmin("IDM Admin") --> PosixAccountIncludesCredMod("POSIX Account - [Includes Cred Mod]") +IdmAdmin("IDM Admin") --> RadiusAccountModify("Radius Account Modify") +``` + +## Integration Admin + +```mermaid +graph LR + +IntegrationAdmin("Integration Admin") --> Oauth2Admin("Oauth2 Admin") +IntegrationAdmin("Integration Admin") --> PosixAccountConsumer("POSIX Account Consumer") +IntegrationAdmin("Integration Admin") --> RadiusServiceAdmin("Radius Service Admin") +``` + +## Help Desk + +```mermaid +graph LR + +HelpDesk("Help Desk") --> PersonCredentialModify("Person Credential Modify") +HelpDesk("Help Desk") --> PersonReadNoPII("Person Read No PII") +``` + +## Account "Self" + +```mermaid +graph LR + +SelfMailModify("Self Mail Modify") --> |"Modifies"| Self +SelfRead("Self Read") --> |"Read"| Self +SelfModify("Self Modify") --> |"Writes Secrets"| Self +SelfNameModify("Self Name Modify") --> |"Modifies"| Self +``` + +## Account-Related + +Duplicated for Service Accounts, HP persons, HP service Accounts. + +```mermaid +graph LR + +PersonOnBoard("Person On Board") --> |"Creates"| Persons("Persons") +PersonAdmin("Person Admin") --> |"Creates Deletes"| Persons("Persons") +PersonPIIModify --> |"Reads Modifies"| Persons +PersonPIIModify("Person PII Modify") -.-> |"Member of"| PersonAdmin +PersonCredentialModify("Person Credential Modify") -.-> |"Member of"| PersonAdmin +PersonCredentialModify("Person Credential Modify") -.-> |"Member of"| PersonOnBoard +PersonCredentialModify --> |"Reads Modifies"| Persons +PersonCredentialModify --> |"Reads"| PersonReadNoPII("Person Read No PII") +PersonAdmin --> PersonReadWithPII("Person Read - With PII") +PersonReadWithPII --> PersonReadNoPII +PersonReadNoPII --> |"Reads"| Persons +PosixAccountIncludesCredMod --> |"Extends (Add Posix Account)"| Persons +``` + +## Domain and Schema + +```mermaid +graph LR + +DomainConfigAdmin("Domain Configuration Admin") --> |"Modifies Reads"| Domain +DomainConfigAdmin("Domain Configuration Admin") --> |"Modifies Reads"| System +SyncAccountAdmin("Sync Account Admin") --> |"Creates Modifies Deletes"| SyncAccounts("Sync Accounts") +SchemaAdmin("Schema Admin") --> |"Creates Modifies"| Schema("Schema") +AccessControlAdmin("Access Control Admin") --> |"Creates Modifies Deletes"| AccessControls("Access Controls") +``` + +## High-Priv and Groups + +```mermaid +graph LR + +GroupAdmin("Group Admin") --> |"Create Modify Delete"| Groups("Groups") +AccountPolicyAdmin("Account Policy Admin") --> |"Modifies Extends"| Groups("Groups") +GroupAdmin --> |"Modify Delete"| HPGroups("HP Groups") +GroupAdmin --> |"Add Members"| HPGroup("HP Group") + +HPGroupAdmin("HP Group Admin") --> HPGroup +GroupAdmin -.-> |"Inherits"| HPGroupAdmin +``` + +## OAuth2 Specific + +```mermaid +graph LR + +Oauth2Admin("Oauth2 Admin") --> |"Creates Modifies Delegates"| Oauth2RS("Oauth2 RS") +ScopedMember("Scoped Member") --> |"Reads"| Oauth2RS +``` + +## POSIX-Specific + +```mermaid +graph LR + +PosixAccountConsumer("POSIX Account Consumer") --> |"Reads Auths"| PosixAccounts("Posix Accounts") +``` + +## Radius + +```mermaid +graph LR + +RadiusServiceAdmin("Radius Service Admin") --> |"Adds Members"| RadiusService("Radius Service") +RadiusService --> |"Reads Secrets"| RadiusAccounts("Radius Accounts") +RadiusAccountModify("Radius Account Modify") --> |"Writes Secrets"| RadiusAccounts +``` + +## Recycle Bin Admin + +```mermaid +graph LR + +RecycleBinAdmin("Recycle Bin Admin") --> |"Modifies Reads Revives"| RecycledEntries("Recycled Entries") +``` diff --git a/book/src/developers/designs/domain_join.md b/book/src/developers/designs/domain_join.md new file mode 100644 index 0000000000..76eb6f1abb --- /dev/null +++ b/book/src/developers/designs/domain_join.md @@ -0,0 +1,128 @@ +# Domain Join - Machine Accounts + +There are a number of features we have been considering that will require us to finally give in and +support machine accounts also know as domain joining. + +## Feature Requirements + +### Limiting Unix Password Auth + +Currently unix password authentication is targetted as the method for sudo. Initial access to the +machine should come from ssh keys (and in future, ctap2). + +In order to maintain compatability with LDAP style authentication, we allow "anonymous hosts" to +retrieve ssh public keys, and then perform sudo authentication. + +This has the obvious caveat that anyone can stand up a machine that trusts a Kanidm instance. This +presents a double edged sword: + +- By configuring a machine to authenticate via Kanidm, there is full trust + in the authentication decisions Kanidm makes. +- Users of Kanidm may be tricked into accessing a machine that is not managed + by their IT or other central authority. + +To prevent this, UNIX authentication should be configurable to prevent usage from unregistered machines. +This will require the machine to present machine authentication credentials simultaneously with the +user's credentials. + +A potential change is removing the current unix password auth mechanism as a whole. Instead the +user's auth token would contain a TPM bound credential that only the domain joined machine's TPM could +access and use. + +### Requesting Cryptographic Credentials + +When a user logs in to a machine, it may be required that they can use that authentication to +identify themself to other systems. When a user authenticates with credentials such as ssh-keys, +it's not possible to use these to request other forwardable credentials - and ssh agent forwarding +only allows forwarding of ssh credentials, not other types of credentials that may be needed. + +In this case when a user authenticates with SSH, since they're using a trusted machine, Kanidm can +request short-term and limited credentials on the users behalf. + +An example is that we could dynamically request TLS certificates or Kerberos credentials. + +Normally with ssh in this manner, everything has to use kerberos. This would force users to kinit on +their machine to ssh and forward their credentials to the next machine. This causes friction since +configuring kerberos on machines is an exercise in frustration, and with BYOD it gets even worse. In +addition when using ssh with an ssh key, the only viable kinit mechanism is password or password + +totp once the user has logged in. This is because pkcs11 can't be forwarded over ssh, nor can CTAP2, +limiting kinit to weaker authentication mechanisms. + +## Security Considerations + +- Anonymous joins should not be allowed or permitted. +- Join tokens need to be revoked (causing related machines to request re-enrollment) or expired + (related machines can continue to function) +- Join tokens must be auditable. +- Private keys SHOULD be stored in a TPM, or at least a software HSM with a secured unlock key. +- The use of the private key must prevent replay attacks + +## Overview + +Since the machine would now be an entity requiring authentication, we need to have a process to +establish and maintain this trust relationship. + +1. A join token is created by a user who is authorised to perform domain joins. +2. The machine is audited for a known trust state. This process may vary from site to site. A future + improvement could be that the join token can only release on certain TPM PCR values. +3. The join token is yielded to the Kanidm UNIX daemon which submits its signing key to the Kanidm + server. +4. The kanidm server verifies the submission and creates a machine account. +5. The kanidm unix daemon now uses it's signing key to sign a challenge that is submitted with all + requests to the kanidm server. + +Extra + +6. Machines should be able to "re-join" with an alternate join token, moving their machine account + join token relationship. +7. Machines must be able to self-enroll newer keys which may have stronger cryptographic + requirements. + +## Details + +### Join Token Creation + +Join tokens are persisted in the database allowing tracing back to the usage of the token. + +Every machine that is joined by that token will related back to that token. This allows auditing of +which token was used to join which machine. + +Machines may re-enroll with an alternate token. + +The join token should be signed. The JWK pub key should be available at a known HTTPS uri so that +the client can use it to validate the join token and its content. This _may_ allow policy to be +embedded into the join token for the client to self-adhere to in the join process. + +### Machine Auditing + +The machine should be audited to be in a secure state. It's not yet clear how to proceed here, but +we should consider using TPM PCRs with secure boot to measure this and validate the machine state. + +One possible way to achieve this could be with full disk encryption that is bound to secure boot and +TPM PCRs. Kanidm-unixd could validate the same PCR's to start operating. The challenge here would be +updates of the expected PCR values during a system update. Alternately, Kanidm could "assume" that +if started, then the FDE must have passed and attestation of health "is out of scope" for us. + +### Public Key Submission + +The private key should be generated and stored in a TPM/HSM. If possible, we should also submit +attestation of this. + +The submission of the public key should prevent replays, and should sign either a nonce or the +current time. The current time must be valid to within a number of seconds. The nonce must be +created by the server. + +The machine must submit its public key, the time value and the signature. This should accompany the +join token. + +If the signature is valid, and the join token is correct, then the machine is joined and has a +machine account created. The machine account is linked to the join token. + +### Machine Account + +The machine account is a new form of account, similar to a service account. It should identify the +machine, its hostname, and other properties. It should also contain the machine's public key id. + +When the machine requests certain API's from Kanidm, it should submit signed requests that include +the current time. The kid is used to find the machine account that is submitting the request. This +then validates the identity of the caller, and then allows the action to proceed.