1
0
mirror of https://github.com/bitwarden/server synced 2025-12-31 15:43:16 +00:00
Files
server/test/Api.Test/KeyManagement/Models/Request/SetKeyConnectorKeyRequestModelTests.cs
Maciej Zieniuk a92d7ac129 [PM-27280] Support v2 encryption on key-connector signups (#6712)
* account v2 registration for key connector

* use new user repository functions

* test coverage

* integration test coverage

* documentation

* code review

* missing test coverage

* fix failing test

* failing test

* incorrect ticket number

* moved back request model to Api, created dedicated data class in Core

* sql stored procedure type mismatch, simplification

* key connector authorization handler
2025-12-18 13:43:03 -05:00

334 lines
9.9 KiB
C#

using System.ComponentModel.DataAnnotations;
using Bit.Api.KeyManagement.Models.Requests;
using Bit.Core;
using Bit.Core.Auth.Models.Api.Request.Accounts;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.KeyManagement.Models.Api.Request;
using Xunit;
namespace Bit.Api.Test.KeyManagement.Models.Request;
public class SetKeyConnectorKeyRequestModelTests
{
private const string _wrappedUserKey = "2.AOs41Hd8OQiCPXjyJKCiDA==|O6OHgt2U2hJGBSNGnimJmg==|iD33s8B69C8JhYYhSa4V1tArjvLr8eEaGqOV7BRo5Jk=";
private const string _publicKey = "public-key";
private const string _privateKey = "private-key";
private const string _userKey = "user-key";
private const string _orgIdentifier = "org-identifier";
[Fact]
public void Validate_V2Registration_Valid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = _wrappedUserKey,
AccountKeys = new AccountKeysRequestModel
{
AccountPublicKey = _publicKey,
UserKeyEncryptedAccountPrivateKey = _privateKey
},
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Empty(results);
}
[Fact]
public void Validate_V2Registration_WrappedUserKeyNotEncryptedString_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = "not-encrypted-string",
AccountKeys = new AccountKeysRequestModel
{
AccountPublicKey = _publicKey,
UserKeyEncryptedAccountPrivateKey = _privateKey
},
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results,
r => r.ErrorMessage == "KeyConnectorKeyWrappedUserKey is not a valid encrypted string.");
}
[Fact]
public void Validate_V1Registration_Valid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Empty(results);
}
[Fact]
public void Validate_V1Registration_MissingKey_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = null,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "Key must be supplied.");
}
[Fact]
public void Validate_V1Registration_MissingKeys_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = null,
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "Keys must be supplied.");
}
[Fact]
public void Validate_V1Registration_MissingKdf_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = null,
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "Kdf must be supplied.");
}
[Fact]
public void Validate_V1Registration_MissingKdfIterations_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = KdfType.PBKDF2_SHA256,
KdfIterations = null,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "KdfIterations must be supplied.");
}
[Fact]
public void Validate_V1Registration_Argon2id_MissingKdfMemory_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = KdfType.Argon2id,
KdfIterations = AuthConstants.ARGON2_ITERATIONS.Default,
KdfMemory = null,
KdfParallelism = AuthConstants.ARGON2_PARALLELISM.Default,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "KdfMemory must be supplied when Kdf is Argon2id.");
}
[Fact]
public void Validate_V1Registration_Argon2id_MissingKdfParallelism_Invalid()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
Key = _userKey,
Keys = new KeysRequestModel
{
PublicKey = _publicKey,
EncryptedPrivateKey = _privateKey
},
Kdf = KdfType.Argon2id,
KdfIterations = AuthConstants.ARGON2_ITERATIONS.Default,
KdfMemory = AuthConstants.ARGON2_MEMORY.Default,
KdfParallelism = null,
OrgIdentifier = _orgIdentifier
};
// Act
var results = Validate(model);
// Assert
Assert.Single(results);
Assert.Contains(results, r => r.ErrorMessage == "KdfParallelism must be supplied when Kdf is Argon2id.");
}
[Fact]
public void ToKeyConnectorKeysData_EmptyKeyConnectorKeyWrappedUserKey_ThrowsException()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = "",
AccountKeys = new AccountKeysRequestModel
{
AccountPublicKey = _publicKey,
UserKeyEncryptedAccountPrivateKey = _privateKey
},
OrgIdentifier = _orgIdentifier
};
// Act
var exception = Assert.Throws<BadRequestException>(() => model.ToKeyConnectorKeysData());
// Assert
Assert.Equal("KeyConnectorKeyWrappedUserKey and AccountKeys must be supplied.", exception.Message);
}
[Fact]
public void ToKeyConnectorKeysData_NullKeyConnectorKeyWrappedUserKey_ThrowsException()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = null,
AccountKeys = new AccountKeysRequestModel
{
AccountPublicKey = _publicKey,
UserKeyEncryptedAccountPrivateKey = _privateKey
},
OrgIdentifier = _orgIdentifier
};
// Act
var exception = Assert.Throws<BadRequestException>(() => model.ToKeyConnectorKeysData());
// Assert
Assert.Equal("KeyConnectorKeyWrappedUserKey and AccountKeys must be supplied.", exception.Message);
}
[Fact]
public void ToKeyConnectorKeysData_NullAccountKeys_ThrowsException()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = _wrappedUserKey,
AccountKeys = null,
OrgIdentifier = _orgIdentifier
};
// Act
var exception = Assert.Throws<BadRequestException>(() => model.ToKeyConnectorKeysData());
// Assert
Assert.Equal("KeyConnectorKeyWrappedUserKey and AccountKeys must be supplied.", exception.Message);
}
[Fact]
public void ToKeyConnectorKeysData_Valid_Success()
{
// Arrange
var model = new SetKeyConnectorKeyRequestModel
{
KeyConnectorKeyWrappedUserKey = _wrappedUserKey,
AccountKeys = new AccountKeysRequestModel
{
AccountPublicKey = _publicKey,
UserKeyEncryptedAccountPrivateKey = _privateKey
},
OrgIdentifier = _orgIdentifier
};
// Act
var data = model.ToKeyConnectorKeysData();
// Assert
Assert.Equal(_wrappedUserKey, data.KeyConnectorKeyWrappedUserKey);
Assert.Equal(_publicKey, data.AccountKeys.AccountPublicKey);
Assert.Equal(_privateKey, data.AccountKeys.UserKeyEncryptedAccountPrivateKey);
Assert.Equal(_orgIdentifier, data.OrgIdentifier);
}
private static List<ValidationResult> Validate(SetKeyConnectorKeyRequestModel model)
{
var results = new List<ValidationResult>();
Validator.TryValidateObject(model, new ValidationContext(model), results, true);
return results;
}
}