Simple User management for single tenant services
Problem
We want to provide easy user management for the AppCat services. The customer should be able to create users, permissions and if available for the given service, databases. The structure of the API should be similar for each service, just like the rest of the AppCat API is similar between services. This decision only concerns itself with services that are single tenant in nature. Cluster-wide services with multi-tenant user management are not part of this decision and will be handled in a separate document.
Goals
-
User management for single tenant services like PostgreSQL, MariaDB, Redis, etc.
-
The user management API should adhere to a convention spanning all services so that it follows the same structure for every service
-
Find a decision for simple service. There might be services in the future that have complex user and RBAC mechanisms that may not fit in this concept and need a custom decision
-
The API should be identical for the same service from different providers, given feature parity of the providers
-
Don’t abstract service specific concepts in the API, this could lead to confusion
Proposals
Generally
Points outlined in this section apply to all proposals.
When choosing a mechanism to manage the users, then we should prefer platform and provider-agnostic solutions before specific ones.
For example provider-sql
can manage PostgreSQL, MySQL and MSSQL directly.
It only needs credentials to connect to the instance.
In contrast, passing the user management to StackGres and let it handle the provisioning, would only work for PostgreSQL by VSHN, and we’d still have to come up with a solution for other PostgreSQL providers.
If there are no crossplane providers or other operators to manage a service, but terraform modules are available, we can leverage Crossplane’s UpJet.
When specifying users, then no passwords can be specified, only the names of the users. Any passwords will be generated by AppCat. Each created user should get its own connection secret in the claim namespace.
Proposal 1: Add user management to claims
Each service exposes the user management under the spec.parameters.service
field in the claims.
Each service needs to be extended with functions that deploy the following:
-
Create a new
secret
from connection detail that satisfies the provider -
Deploy a
providerConfig
-
Deploy a managed resource for the provider for each user/database/grant
There’s a POC for this in component-appcat and AppCat.
Example:
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNPostgreSQL
metadata:
name: my-pg
spec:
parameters:
...
service:
users: (1)
- prod
- test
- int
databases: (2)
- prod
- int
- test
grants: (3)
- privileges:
- ALL
type: GRANT
user: prod
database: prod
1 | Generic for PostgreSQL, MariaDB and potentially more |
2 | Generic for PostgreSQL and MariaDB |
3 | PostgreSQL specific, modelled after provider-sql 's CRDs.
|
Proposal 2: User management separate of claims
Each service has additional XRDs that manage the user and permissions for the given service.
There are two variations how this could be done. Having a reference to the instance in the user management XRD. Or Having a reference for the user management XRD in the main claim.
The complexity of this solution will be much higher:
-
Each service needs a new XRD
-
Each of these XRDs need a new composition
-
Each of these XRDs need a new composition function
-
The function itself first needs to resolve the references before it can actually deploy the necessary configurations for the provider
Example reference on management object:
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNPostgreSQL
metadata:
name: my-pg
spec:
parameters: {}
---
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNPostgreSQLIAM
metadata:
name: myiam
spec:
parameters:
postgreSQLClaimRef:
name: my-pg
service:
users: (1)
- prod
- test
- int
databases: (2)
- prod
- int
- test
grants: (3)
- privileges:
- ALL
type: GRANT
user: prod
database: prod
1 | Generic for PostgreSQL, MariaDB and potentially more |
2 | Generic for PostgreSQL and MariaDB |
3 | PostgreSQL specific, modelled after provider-sql 's CRDs. |
Example reference on claim:
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNPostgreSQL
metadata:
name: my-pg
spec:
parameters:
service:
iamRefs:
- myiam
---
apiVersion: vshn.appcat.vshn.io/v1
kind: VSHNPostgreSQLIAM
metadata:
name: myiam
spec:
parameters:
users: (1)
- prod
- test
- int
databases: (2)
- prod
- int
- test
grants: (3)
- privileges:
- ALL
type: GRANT
user: prod
database: prod
1 | Generic for PostgreSQL, MariaDB and potentially more |
2 | Generic for PostgreSQL and MariaDB |
3 | PostgreSQL specific, modelled after provider-sql 's CRDs.
|
Decision
Proposal 1.
Rationale
Adding the user management to the claim is the most straight forward solution. Managing the users in a separate XRD increases the complexity by a lot. It requires separate compositions and composition functions to be able to work. It also makes it harder for the end-user to use. They have to make sure that the references are correct, which can be annoying.