forked from kanidm/kanidm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |