1
0
mirror of https://github.com/bitwarden/server synced 2026-01-07 11:03:37 +00:00

[EC-261] SCIM (#2105)

* scim project stub

* some scim models and v2 controllers

* implement some v2 scim endpoints

* fix spacing

* api key auth

* EC-261 - SCIM Org API Key and connection type config

* EC-261 - Fix lint errors/formatting

* updates for okta implementation testing

* fix var ref

* updates from testing with Okta

* implement scim context via provider parsing

* support single and list of ids for add/remove groups

* log ops not handled

* touch up scim context

* group list filtering

* EC-261 - Additional SCIM provider types

* EC-265 - UseScim flag and license update

* EC-265 - SCIM provider type of default (0)

* EC-265 - Add Scim URL and update connection validation

* EC-265 - Model validation and cleanup for SCIM keys

* implement scim org connection

* EC-265 - Ensure ServiceUrl is not persisted to DB

* EC-265 - Exclude provider type from DB if not configured

* EC-261 - EF Migrations for SCIM

* add docker builds for scim

* EC-261 - Fix failing permissions tests

* EC-261 - Fix unit tests and pgsql migrations

* Formatting fixes from linter

* EC-265 - Remove service URL from scim config

* EC-265 - Fix unit tests, removed wayward validation

* EC-265 - Require self-hosted for billing sync org conn

* EC-265 - Fix formatting issues - whitespace

* EC-261 - PR feedback and cleanup

* scim constants rename

* no scim settings right now

* update project name

* delete package lock

* update appsettings configs for scim

* use default scim provider for context

Co-authored-by: Kyle Spearrin <kyle.spearrin@gmail.com>
This commit is contained in:
Chad Scharf
2022-07-14 15:58:48 -04:00
committed by GitHub
parent c5852db6ed
commit 19b8d8281a
117 changed files with 8553 additions and 169 deletions

View File

@@ -0,0 +1,373 @@
IF COL_LENGTH('[dbo].[Organization]', 'UseScim') IS NULL
BEGIN
ALTER TABLE
[dbo].[Organization]
ADD
[UseScim] BIT NOT NULL CONSTRAINT [DF_Organization_UseScim] DEFAULT (0);
END
GO
CREATE OR ALTER VIEW [dbo].[OrganizationUserOrganizationDetailsView]
AS
SELECT
OU.[UserId],
OU.[OrganizationId],
O.[Name],
O.[Enabled],
O.[UsePolicies],
O.[UseSso],
O.[UseKeyConnector],
O.[UseScim],
O.[UseGroups],
O.[UseDirectory],
O.[UseEvents],
O.[UseTotp],
O.[Use2fa],
O.[UseApi],
O.[UseResetPassword],
O.[SelfHost],
O.[UsersGetPremium],
O.[Seats],
O.[MaxCollections],
O.[MaxStorageGb],
O.[Identifier],
OU.[Key],
OU.[ResetPasswordKey],
O.[PublicKey],
O.[PrivateKey],
OU.[Status],
OU.[Type],
SU.[ExternalId] SsoExternalId,
OU.[Permissions],
PO.[ProviderId],
P.[Name] ProviderName,
SS.[Data] SsoConfig
FROM
[dbo].[OrganizationUser] OU
INNER JOIN
[dbo].[Organization] O ON O.[Id] = OU.[OrganizationId]
LEFT JOIN
[dbo].[SsoUser] SU ON SU.[UserId] = OU.[UserId] AND SU.[OrganizationId] = OU.[OrganizationId]
LEFT JOIN
[dbo].[ProviderOrganization] PO ON PO.[OrganizationId] = O.[Id]
LEFT JOIN
[dbo].[Provider] P ON P.[Id] = PO.[ProviderId]
LEFT JOIN
[dbo].[SsoConfig] SS ON SS.[OrganizationId] = OU.[OrganizationId]
GO
CREATE OR ALTER VIEW [dbo].[ProviderUserProviderOrganizationDetailsView]
AS
SELECT
PU.[UserId],
PO.[OrganizationId],
O.[Name],
O.[Enabled],
O.[UsePolicies],
O.[UseSso],
O.[UseKeyConnector],
O.[UseScim],
O.[UseGroups],
O.[UseDirectory],
O.[UseEvents],
O.[UseTotp],
O.[Use2fa],
O.[UseApi],
O.[UseResetPassword],
O.[SelfHost],
O.[UsersGetPremium],
O.[Seats],
O.[MaxCollections],
O.[MaxStorageGb],
O.[Identifier],
PO.[Key],
O.[PublicKey],
O.[PrivateKey],
PU.[Status],
PU.[Type],
PO.[ProviderId],
PU.[Id] ProviderUserId,
P.[Name] ProviderName
FROM
[dbo].[ProviderUser] PU
INNER JOIN
[dbo].[ProviderOrganization] PO ON PO.[ProviderId] = PU.[ProviderId]
INNER JOIN
[dbo].[Organization] O ON O.[Id] = PO.[OrganizationId]
INNER JOIN
[dbo].[Provider] P ON P.[Id] = PU.[ProviderId]
GO
CREATE OR ALTER PROCEDURE [dbo].[Organization_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@Identifier NVARCHAR(50),
@Name NVARCHAR(50),
@BusinessName NVARCHAR(50),
@BusinessAddress1 NVARCHAR(50),
@BusinessAddress2 NVARCHAR(50),
@BusinessAddress3 NVARCHAR(50),
@BusinessCountry VARCHAR(2),
@BusinessTaxNumber NVARCHAR(30),
@BillingEmail NVARCHAR(256),
@Plan NVARCHAR(50),
@PlanType TINYINT,
@Seats INT,
@MaxCollections SMALLINT,
@UsePolicies BIT,
@UseSso BIT,
@UseGroups BIT,
@UseDirectory BIT,
@UseEvents BIT,
@UseTotp BIT,
@Use2fa BIT,
@UseApi BIT,
@UseResetPassword BIT,
@SelfHost BIT,
@UsersGetPremium BIT,
@Storage BIGINT,
@MaxStorageGb SMALLINT,
@Gateway TINYINT,
@GatewayCustomerId VARCHAR(50),
@GatewaySubscriptionId VARCHAR(50),
@ReferenceData VARCHAR(MAX),
@Enabled BIT,
@LicenseKey VARCHAR(100),
@PublicKey VARCHAR(MAX),
@PrivateKey VARCHAR(MAX),
@TwoFactorProviders NVARCHAR(MAX),
@ExpirationDate DATETIME2(7),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@OwnersNotifiedOfAutoscaling DATETIME2(7),
@MaxAutoscaleSeats INT,
@UseKeyConnector BIT = 0,
@UseScim BIT = 0
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[Organization]
(
[Id],
[Identifier],
[Name],
[BusinessName],
[BusinessAddress1],
[BusinessAddress2],
[BusinessAddress3],
[BusinessCountry],
[BusinessTaxNumber],
[BillingEmail],
[Plan],
[PlanType],
[Seats],
[MaxCollections],
[UsePolicies],
[UseSso],
[UseGroups],
[UseDirectory],
[UseEvents],
[UseTotp],
[Use2fa],
[UseApi],
[UseResetPassword],
[SelfHost],
[UsersGetPremium],
[Storage],
[MaxStorageGb],
[Gateway],
[GatewayCustomerId],
[GatewaySubscriptionId],
[ReferenceData],
[Enabled],
[LicenseKey],
[PublicKey],
[PrivateKey],
[TwoFactorProviders],
[ExpirationDate],
[CreationDate],
[RevisionDate],
[OwnersNotifiedOfAutoscaling],
[MaxAutoscaleSeats],
[UseKeyConnector],
[UseScim]
)
VALUES
(
@Id,
@Identifier,
@Name,
@BusinessName,
@BusinessAddress1,
@BusinessAddress2,
@BusinessAddress3,
@BusinessCountry,
@BusinessTaxNumber,
@BillingEmail,
@Plan,
@PlanType,
@Seats,
@MaxCollections,
@UsePolicies,
@UseSso,
@UseGroups,
@UseDirectory,
@UseEvents,
@UseTotp,
@Use2fa,
@UseApi,
@UseResetPassword,
@SelfHost,
@UsersGetPremium,
@Storage,
@MaxStorageGb,
@Gateway,
@GatewayCustomerId,
@GatewaySubscriptionId,
@ReferenceData,
@Enabled,
@LicenseKey,
@PublicKey,
@PrivateKey,
@TwoFactorProviders,
@ExpirationDate,
@CreationDate,
@RevisionDate,
@OwnersNotifiedOfAutoscaling,
@MaxAutoscaleSeats,
@UseKeyConnector,
@UseScim
)
END
GO
CREATE OR ALTER PROCEDURE [dbo].[Organization_Update]
@Id UNIQUEIDENTIFIER,
@Identifier NVARCHAR(50),
@Name NVARCHAR(50),
@BusinessName NVARCHAR(50),
@BusinessAddress1 NVARCHAR(50),
@BusinessAddress2 NVARCHAR(50),
@BusinessAddress3 NVARCHAR(50),
@BusinessCountry VARCHAR(2),
@BusinessTaxNumber NVARCHAR(30),
@BillingEmail NVARCHAR(256),
@Plan NVARCHAR(50),
@PlanType TINYINT,
@Seats INT,
@MaxCollections SMALLINT,
@UsePolicies BIT,
@UseSso BIT,
@UseGroups BIT,
@UseDirectory BIT,
@UseEvents BIT,
@UseTotp BIT,
@Use2fa BIT,
@UseApi BIT,
@UseResetPassword BIT,
@SelfHost BIT,
@UsersGetPremium BIT,
@Storage BIGINT,
@MaxStorageGb SMALLINT,
@Gateway TINYINT,
@GatewayCustomerId VARCHAR(50),
@GatewaySubscriptionId VARCHAR(50),
@ReferenceData VARCHAR(MAX),
@Enabled BIT,
@LicenseKey VARCHAR(100),
@PublicKey VARCHAR(MAX),
@PrivateKey VARCHAR(MAX),
@TwoFactorProviders NVARCHAR(MAX),
@ExpirationDate DATETIME2(7),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@OwnersNotifiedOfAutoscaling DATETIME2(7),
@MaxAutoscaleSeats INT,
@UseKeyConnector BIT = 0,
@UseScim BIT = 0
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[Organization]
SET
[Identifier] = @Identifier,
[Name] = @Name,
[BusinessName] = @BusinessName,
[BusinessAddress1] = @BusinessAddress1,
[BusinessAddress2] = @BusinessAddress2,
[BusinessAddress3] = @BusinessAddress3,
[BusinessCountry] = @BusinessCountry,
[BusinessTaxNumber] = @BusinessTaxNumber,
[BillingEmail] = @BillingEmail,
[Plan] = @Plan,
[PlanType] = @PlanType,
[Seats] = @Seats,
[MaxCollections] = @MaxCollections,
[UsePolicies] = @UsePolicies,
[UseSso] = @UseSso,
[UseGroups] = @UseGroups,
[UseDirectory] = @UseDirectory,
[UseEvents] = @UseEvents,
[UseTotp] = @UseTotp,
[Use2fa] = @Use2fa,
[UseApi] = @UseApi,
[UseResetPassword] = @UseResetPassword,
[SelfHost] = @SelfHost,
[UsersGetPremium] = @UsersGetPremium,
[Storage] = @Storage,
[MaxStorageGb] = @MaxStorageGb,
[Gateway] = @Gateway,
[GatewayCustomerId] = @GatewayCustomerId,
[GatewaySubscriptionId] = @GatewaySubscriptionId,
[ReferenceData] = @ReferenceData,
[Enabled] = @Enabled,
[LicenseKey] = @LicenseKey,
[PublicKey] = @PublicKey,
[PrivateKey] = @PrivateKey,
[TwoFactorProviders] = @TwoFactorProviders,
[ExpirationDate] = @ExpirationDate,
[CreationDate] = @CreationDate,
[RevisionDate] = @RevisionDate,
[OwnersNotifiedOfAutoscaling] = @OwnersNotifiedOfAutoscaling,
[MaxAutoscaleSeats] = @MaxAutoscaleSeats,
[UseKeyConnector] = @UseKeyConnector,
[UseScim] = @UseScim
WHERE
[Id] = @Id
END
GO
CREATE OR ALTER PROCEDURE [dbo].[Organization_ReadAbilities]
AS
BEGIN
SET NOCOUNT ON
SELECT
[Id],
[UseEvents],
[Use2fa],
CASE
WHEN [Use2fa] = 1 AND [TwoFactorProviders] IS NOT NULL AND [TwoFactorProviders] != '{}' THEN
1
ELSE
0
END AS [Using2fa],
[UsersGetPremium],
[UseSso],
[UseKeyConnector],
[UseScim],
[UseResetPassword],
[Enabled]
FROM
[dbo].[Organization]
END
GO
-- Enable Existing Enterprise Customers to use SCIM
UPDATE [dbo].[Organization]
SET [UseScim] = 1
WHERE [PlanType] IN (10, 11) -- New Enterprise Annual/Monthly (not 2019)
AND [UseScim] = 0;
GO

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Bit.MySqlMigrations.Migrations
{
public partial class UseScimFlag : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "UseScim",
table: "Organization",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "UseScim",
table: "Organization");
}
}
}

View File

@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Bit.MySqlMigrations.Migrations
{
[DbContext(typeof(DatabaseContext))]
@@ -14,8 +16,8 @@ namespace Bit.MySqlMigrations.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.12");
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b =>
{
@@ -61,7 +63,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Cipher");
b.ToTable("Cipher", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b =>
@@ -89,7 +91,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Collection");
b.ToTable("Collection", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b =>
@@ -104,7 +106,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("CipherId");
b.ToTable("CollectionCipher");
b.ToTable("CollectionCipher", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b =>
@@ -188,7 +190,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Device");
b.ToTable("Device", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b =>
@@ -236,7 +238,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("GrantorId");
b.ToTable("EmergencyAccess");
b.ToTable("EmergencyAccess", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b =>
@@ -295,7 +297,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("Event");
b.ToTable("Event", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b =>
@@ -319,7 +321,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Folder");
b.ToTable("Folder", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Grant", b =>
@@ -362,7 +364,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Key");
b.ToTable("Grant");
b.ToTable("Grant", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b =>
@@ -394,7 +396,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Group");
b.ToTable("Group", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b =>
@@ -414,7 +416,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("GroupUser");
b.ToTable("GroupUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b =>
@@ -438,7 +440,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("Installation");
b.ToTable("Installation", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b =>
@@ -573,6 +575,9 @@ namespace Bit.MySqlMigrations.Migrations
b.Property<bool>("UseResetPassword")
.HasColumnType("tinyint(1)");
b.Property<bool>("UseScim")
.HasColumnType("tinyint(1)");
b.Property<bool>("UseSso")
.HasColumnType("tinyint(1)");
@@ -584,7 +589,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("Organization");
b.ToTable("Organization", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b =>
@@ -609,7 +614,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("OrganizationApiKey");
b.ToTable("OrganizationApiKey", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b =>
@@ -633,7 +638,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("OrganizationConnection");
b.ToTable("OrganizationConnection", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b =>
@@ -676,7 +681,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("SponsoringOrganizationId");
b.ToTable("OrganizationSponsorship");
b.ToTable("OrganizationSponsorship", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b =>
@@ -728,7 +733,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("OrganizationUser");
b.ToTable("OrganizationUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b =>
@@ -758,7 +763,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Policy");
b.ToTable("Policy", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b =>
@@ -807,7 +812,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("Provider");
b.ToTable("Provider", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b =>
@@ -839,7 +844,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("ProviderId");
b.ToTable("ProviderOrganization");
b.ToTable("ProviderOrganization", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b =>
@@ -880,7 +885,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("ProviderUser");
b.ToTable("ProviderUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b =>
@@ -937,7 +942,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Send");
b.ToTable("Send", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b =>
@@ -965,7 +970,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("SsoConfig");
b.ToTable("SsoConfig", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b =>
@@ -993,7 +998,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("SsoUser");
b.ToTable("SsoUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b =>
@@ -1022,7 +1027,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("TaxRate");
b.ToTable("TaxRate", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b =>
@@ -1071,7 +1076,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Transaction");
b.ToTable("Transaction", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b =>
@@ -1200,7 +1205,7 @@ namespace Bit.MySqlMigrations.Migrations
b.HasKey("Id");
b.ToTable("User");
b.ToTable("User", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b =>

View File

@@ -0,0 +1,17 @@
START TRANSACTION;
ALTER TABLE `OrganizationUser` MODIFY COLUMN `Status` smallint NOT NULL;
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
VALUES ('20220608191914_DeactivatedUserStatus', '6.0.4');
COMMIT;
START TRANSACTION;
ALTER TABLE `Organization` ADD `UseScim` tinyint(1) NOT NULL DEFAULT FALSE;
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
VALUES ('20220707163017_UseScimFlag', '6.0.4');
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Bit.PostgresMigrations.Migrations
{
public partial class UseScimFlag : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "UseScim",
table: "Organization",
type: "boolean",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "UseScim",
table: "Organization");
}
}
}

View File

@@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Bit.PostgresMigrations.Migrations
{
[DbContext(typeof(DatabaseContext))]
@@ -16,9 +18,10 @@ namespace Bit.PostgresMigrations.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:CollationDefinition:postgresIndetermanisticCollation", "en-u-ks-primary,en-u-ks-primary,icu,False")
.HasAnnotation("Relational:MaxIdentifierLength", 63)
.HasAnnotation("ProductVersion", "5.0.12")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b =>
{
@@ -64,7 +67,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Cipher");
b.ToTable("Cipher", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b =>
@@ -92,7 +95,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Collection");
b.ToTable("Collection", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b =>
@@ -107,7 +110,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("CipherId");
b.ToTable("CollectionCipher");
b.ToTable("CollectionCipher", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b =>
@@ -191,7 +194,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Device");
b.ToTable("Device", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b =>
@@ -239,7 +242,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("GrantorId");
b.ToTable("EmergencyAccess");
b.ToTable("EmergencyAccess", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b =>
@@ -298,7 +301,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("Event");
b.ToTable("Event", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b =>
@@ -322,7 +325,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Folder");
b.ToTable("Folder", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Grant", b =>
@@ -365,7 +368,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Key");
b.ToTable("Grant");
b.ToTable("Grant", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b =>
@@ -397,7 +400,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Group");
b.ToTable("Group", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b =>
@@ -417,7 +420,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("GroupUser");
b.ToTable("GroupUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b =>
@@ -441,7 +444,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("Installation");
b.ToTable("Installation", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b =>
@@ -577,6 +580,9 @@ namespace Bit.PostgresMigrations.Migrations
b.Property<bool>("UseResetPassword")
.HasColumnType("boolean");
b.Property<bool>("UseScim")
.HasColumnType("boolean");
b.Property<bool>("UseSso")
.HasColumnType("boolean");
@@ -588,7 +594,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("Organization");
b.ToTable("Organization", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b =>
@@ -613,7 +619,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("OrganizationApiKey");
b.ToTable("OrganizationApiKey", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b =>
@@ -637,7 +643,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("OrganizationConnection");
b.ToTable("OrganizationConnection", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b =>
@@ -680,7 +686,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("SponsoringOrganizationId");
b.ToTable("OrganizationSponsorship");
b.ToTable("OrganizationSponsorship", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b =>
@@ -717,7 +723,7 @@ namespace Bit.PostgresMigrations.Migrations
b.Property<DateTime>("RevisionDate")
.HasColumnType("timestamp without time zone");
b.Property<byte>("Status")
b.Property<short>("Status")
.HasColumnType("smallint");
b.Property<byte>("Type")
@@ -732,7 +738,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("OrganizationUser");
b.ToTable("OrganizationUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b =>
@@ -762,7 +768,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("Policy");
b.ToTable("Policy", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b =>
@@ -811,7 +817,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("Provider");
b.ToTable("Provider", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b =>
@@ -843,7 +849,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("ProviderId");
b.ToTable("ProviderOrganization");
b.ToTable("ProviderOrganization", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b =>
@@ -884,7 +890,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("ProviderUser");
b.ToTable("ProviderUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b =>
@@ -941,15 +947,16 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Send");
b.ToTable("Send", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("timestamp without time zone");
@@ -970,15 +977,16 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("OrganizationId");
b.ToTable("SsoConfig");
b.ToTable("SsoConfig", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("timestamp without time zone");
@@ -1000,7 +1008,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("SsoUser");
b.ToTable("SsoUser", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b =>
@@ -1029,7 +1037,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("TaxRate");
b.ToTable("TaxRate", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b =>
@@ -1078,7 +1086,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasIndex("UserId");
b.ToTable("Transaction");
b.ToTable("Transaction", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b =>
@@ -1208,7 +1216,7 @@ namespace Bit.PostgresMigrations.Migrations
b.HasKey("Id");
b.ToTable("User");
b.ToTable("User", (string)null);
});
modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b =>

View File

@@ -1,6 +1,6 @@
START TRANSACTION;
ALTER TABLE "User" ADD "UnknownDeviceVerificationEnabled" boolean NOT NULL DEFAULT 1;
ALTER TABLE "User" ADD "UnknownDeviceVerificationEnabled" boolean NOT NULL DEFAULT true;
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220524170740_DeviceUnknownVerification', '5.0.12');

View File

@@ -0,0 +1,8 @@
START TRANSACTION;
ALTER TABLE "Organization" ADD "UseScim" boolean NOT NULL DEFAULT FALSE;
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20220707162231_UseScimFlag', '6.0.4');
COMMIT;

View File

@@ -103,6 +103,9 @@ namespace Bit.Setup
[Description("Enable Key Connector (https://bitwarden.com/help/article/deploy-key-connector)")]
public bool EnableKeyConnector { get; set; } = false;
[Description("Enable SCIM")]
public bool EnableScim { get; set; } = false;
[YamlIgnore]
public string Domain
{

View File

@@ -48,6 +48,7 @@
}
MssqlDataDockerVolume = context.Config.DatabaseDockerVolume;
EnableKeyConnector = context.Config.EnableKeyConnector;
EnableScim = context.Config.EnableScim;
HttpPort = context.Config.HttpPort;
HttpsPort = context.Config.HttpsPort;
if (!string.IsNullOrWhiteSpace(context.CoreVersion))
@@ -67,6 +68,7 @@
public string ComposeVersion { get; set; } = "3";
public bool MssqlDataDockerVolume { get; set; }
public bool EnableKeyConnector { get; set; }
public bool EnableScim { get; set; }
public string HttpPort { get; set; }
public string HttpsPort { get; set; }
public bool HasPort => !string.IsNullOrWhiteSpace(HttpPort) || !string.IsNullOrWhiteSpace(HttpsPort);

View File

@@ -68,6 +68,7 @@
Captcha = context.Config.Captcha;
Ssl = context.Config.Ssl;
EnableKeyConnector = context.Config.EnableKeyConnector;
EnableScim = context.Config.EnableScim;
Domain = context.Config.Domain;
Url = context.Config.Url;
RealIps = context.Config.RealIps;
@@ -116,6 +117,7 @@
public bool Captcha { get; set; }
public bool Ssl { get; set; }
public bool EnableKeyConnector { get; set; }
public bool EnableScim { get; set; }
public string Domain { get; set; }
public string Url { get; set; }
public string CertificatePath { get; set; }

View File

@@ -211,6 +211,23 @@ services:
- default
- public
{{/if}}
{{#if EnableScim}}
scim:
image: bitwarden/scim:{{{CoreVersion}}}
container_name: bitwarden-scim
restart: always
volumes:
- ../ca-certificates:/etc/bitwarden/ca-certificates
- ../logs/api:/etc/bitwarden/logs
env_file:
- global.env
- ../env/uid.env
- ../env/global.override.env
networks:
- default
- public
{{/if}}
{{#if MssqlDataDockerVolume}}
volumes:

View File

@@ -104,7 +104,7 @@ server {
location = /captcha-connector.html {
proxy_pass http://web:5000/captcha-connector.html;
}
location = /captcha-mobile-connector.html {
proxy_pass http://web:5000/captcha-mobile-connector.html;
}
@@ -168,4 +168,10 @@ server {
proxy_pass http://key-connector:5000/;
}
{{/if}}
{{#if EnableScim}}
location /scim/ {
proxy_pass http://scim:5000/;
}
{{/if}}
}