Skip to content

Support MSSQL contained database user #298

@baburciu

Description

@baburciu

What problem are you facing?

When working with MSSQL Server contained databases, the current provider-sql implementation only supports creating traditional server-level LOGINs followed by database users mapped to those logins. However, MSSQL Server supports contained database users that exist entirely within a specific database without requiring a server-level login.

Our use-case involves creating database users that should be scoped only to specific databases without having server-level access, particularly important for (Azure) Databases that are geo-replicated where we'd want the user to be created in the primary database and get automatically replicated to the read-replica.

Currently, when trying to create users in a contained database context, we encounter errors like "User must be in the master database" (when trying to skip loginDatabase or to set it to some loginDatabase: foo database in which we'd want the user to be contained) because the provider attempts to create server-level LOGINs in the target database instead of using the contained user pattern.

How could Crossplane provider-sql help solve your problem?

The provider-sql could support contained database users.
One implementation idea could be to adding a new optional field contained: true to the MSSQL User resource specification, based on which the provider should:

  1. Use the CREATE USER [username] WITH PASSWORD = 'password' syntax directly in the target database
  2. Skip the traditional CREATE LOGIN step that's performed at the server level
  3. Allow password updates using ALTER USER [username] WITH PASSWORD = 'new_password'
  4. Handle user deletion by dropping only the database user (no server-level login to clean up)

This approach would enable compatibility with existing Grant resources (which operate at database level)
and backward compatibility for User resources INSTANCE authentication type level (default behavior unchanged when contained is false/unset).

Example usage:

apiVersion: mssql.sql.crossplane.io/v1alpha1
kind: User
metadata:
  name: contained-user
spec:
  forProvider:
    database: myapp-db
    contained: true  # new option enabling contained user creation, that expects no `loginDatabase`/`loginDatabaseRef`/`loginDatabaseSelector`
    passwordSecretRef:
      name: user-password
      namespace: default
      key: password
  providerConfigRef:
    name: myapp-db-instance-connection

This would create a user that exists only within myapp-db with authentication_type_desc: DATABASE instead of the traditional authentication_type_desc: INSTANCE approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions