Skip to content

Commit

Permalink
Add design diagrams (kanidm#2332)
Browse files Browse the repository at this point in the history
  • Loading branch information
Firstyear authored Jan 4, 2024
1 parent bdb3933 commit 38f930c
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 0 deletions.
2 changes: 2 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
162 changes: 162 additions & 0 deletions book/src/developers/designs/access_control_defaults.md
Original file line number Diff line number Diff line change
@@ -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")
```
128 changes: 128 additions & 0 deletions book/src/developers/designs/domain_join.md
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 38f930c

Please sign in to comment.