mirror of
https://github.com/bitwarden/server.git
synced 2024-11-24 12:35:25 +01:00
[PM-10394] Add new item type ssh key (#4575)
* Add ssh key item type * Add fingerprint * Limit ssh key ciphers to new clients * Fix enc string length for 4096 bit rsa keys * Remove keyAlgorithm from ssh cipher * Add featureflag and exclude mobile from sync * Add ssh-agent flag
This commit is contained in:
parent
50f7fa03db
commit
dae493db72
@ -1,7 +1,9 @@
|
|||||||
using Bit.Api.Vault.Models.Response;
|
using Bit.Api.Vault.Models.Response;
|
||||||
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
@ -10,6 +12,7 @@ using Bit.Core.Repositories;
|
|||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Core.Tools.Repositories;
|
using Bit.Core.Tools.Repositories;
|
||||||
|
using Bit.Core.Vault.Models.Data;
|
||||||
using Bit.Core.Vault.Repositories;
|
using Bit.Core.Vault.Repositories;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@ -30,6 +33,8 @@ public class SyncController : Controller
|
|||||||
private readonly IPolicyRepository _policyRepository;
|
private readonly IPolicyRepository _policyRepository;
|
||||||
private readonly ISendRepository _sendRepository;
|
private readonly ISendRepository _sendRepository;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
private readonly ICurrentContext _currentContext;
|
||||||
|
private readonly Version _sshKeyCipherMinimumVersion = new(Constants.SSHKeyCipherMinimumVersion);
|
||||||
private readonly IFeatureService _featureService;
|
private readonly IFeatureService _featureService;
|
||||||
|
|
||||||
public SyncController(
|
public SyncController(
|
||||||
@ -43,6 +48,7 @@ public class SyncController : Controller
|
|||||||
IPolicyRepository policyRepository,
|
IPolicyRepository policyRepository,
|
||||||
ISendRepository sendRepository,
|
ISendRepository sendRepository,
|
||||||
GlobalSettings globalSettings,
|
GlobalSettings globalSettings,
|
||||||
|
ICurrentContext currentContext,
|
||||||
IFeatureService featureService)
|
IFeatureService featureService)
|
||||||
{
|
{
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
@ -55,6 +61,7 @@ public class SyncController : Controller
|
|||||||
_policyRepository = policyRepository;
|
_policyRepository = policyRepository;
|
||||||
_sendRepository = sendRepository;
|
_sendRepository = sendRepository;
|
||||||
_globalSettings = globalSettings;
|
_globalSettings = globalSettings;
|
||||||
|
_currentContext = currentContext;
|
||||||
_featureService = featureService;
|
_featureService = featureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +84,8 @@ public class SyncController : Controller
|
|||||||
var hasEnabledOrgs = organizationUserDetails.Any(o => o.Enabled);
|
var hasEnabledOrgs = organizationUserDetails.Any(o => o.Enabled);
|
||||||
|
|
||||||
var folders = await _folderRepository.GetManyByUserIdAsync(user.Id);
|
var folders = await _folderRepository.GetManyByUserIdAsync(user.Id);
|
||||||
var ciphers = await _cipherRepository.GetManyByUserIdAsync(user.Id, withOrganizations: hasEnabledOrgs);
|
var allCiphers = await _cipherRepository.GetManyByUserIdAsync(user.Id, withOrganizations: hasEnabledOrgs);
|
||||||
|
var ciphers = FilterSSHKeys(allCiphers);
|
||||||
var sends = await _sendRepository.GetManyByUserIdAsync(user.Id);
|
var sends = await _sendRepository.GetManyByUserIdAsync(user.Id);
|
||||||
|
|
||||||
IEnumerable<CollectionDetails> collections = null;
|
IEnumerable<CollectionDetails> collections = null;
|
||||||
@ -101,4 +109,16 @@ public class SyncController : Controller
|
|||||||
folders, collections, ciphers, collectionCiphersGroupDict, excludeDomains, policies, sends);
|
folders, collections, ciphers, collectionCiphersGroupDict, excludeDomains, policies, sends);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ICollection<CipherDetails> FilterSSHKeys(ICollection<CipherDetails> ciphers)
|
||||||
|
{
|
||||||
|
if (_currentContext.ClientVersion >= _sshKeyCipherMinimumVersion)
|
||||||
|
{
|
||||||
|
return ciphers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ciphers.Where(c => c.Type != Core.Vault.Enums.CipherType.SSHKey).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
26
src/Api/Vault/Models/CipherSSHKeyModel.cs
Normal file
26
src/Api/Vault/Models/CipherSSHKeyModel.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Bit.Core.Vault.Models.Data;
|
||||||
|
|
||||||
|
namespace Bit.Api.Vault.Models;
|
||||||
|
|
||||||
|
public class CipherSSHKeyModel
|
||||||
|
{
|
||||||
|
public CipherSSHKeyModel() { }
|
||||||
|
|
||||||
|
public CipherSSHKeyModel(CipherSSHKeyData data)
|
||||||
|
{
|
||||||
|
PrivateKey = data.PrivateKey;
|
||||||
|
PublicKey = data.PublicKey;
|
||||||
|
KeyFingerprint = data.KeyFingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
|
[EncryptedString]
|
||||||
|
[EncryptedStringLength(5000)]
|
||||||
|
public string PrivateKey { get; set; }
|
||||||
|
[EncryptedString]
|
||||||
|
[EncryptedStringLength(5000)]
|
||||||
|
public string PublicKey { get; set; }
|
||||||
|
[EncryptedString]
|
||||||
|
[EncryptedStringLength(1000)]
|
||||||
|
public string KeyFingerprint { get; set; }
|
||||||
|
}
|
@ -37,6 +37,7 @@ public class CipherRequestModel
|
|||||||
public CipherCardModel Card { get; set; }
|
public CipherCardModel Card { get; set; }
|
||||||
public CipherIdentityModel Identity { get; set; }
|
public CipherIdentityModel Identity { get; set; }
|
||||||
public CipherSecureNoteModel SecureNote { get; set; }
|
public CipherSecureNoteModel SecureNote { get; set; }
|
||||||
|
public CipherSSHKeyModel SSHKey { get; set; }
|
||||||
public DateTime? LastKnownRevisionDate { get; set; } = null;
|
public DateTime? LastKnownRevisionDate { get; set; } = null;
|
||||||
|
|
||||||
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
|
public CipherDetails ToCipherDetails(Guid userId, bool allowOrgIdSet = true)
|
||||||
@ -82,6 +83,9 @@ public class CipherRequestModel
|
|||||||
case CipherType.SecureNote:
|
case CipherType.SecureNote:
|
||||||
existingCipher.Data = JsonSerializer.Serialize(ToCipherSecureNoteData(), JsonHelpers.IgnoreWritingNull);
|
existingCipher.Data = JsonSerializer.Serialize(ToCipherSecureNoteData(), JsonHelpers.IgnoreWritingNull);
|
||||||
break;
|
break;
|
||||||
|
case CipherType.SSHKey:
|
||||||
|
existingCipher.Data = JsonSerializer.Serialize(ToCipherSSHKeyData(), JsonHelpers.IgnoreWritingNull);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
|
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
|
||||||
}
|
}
|
||||||
@ -230,6 +234,21 @@ public class CipherRequestModel
|
|||||||
Type = SecureNote.Type,
|
Type = SecureNote.Type,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CipherSSHKeyData ToCipherSSHKeyData()
|
||||||
|
{
|
||||||
|
return new CipherSSHKeyData
|
||||||
|
{
|
||||||
|
Name = Name,
|
||||||
|
Notes = Notes,
|
||||||
|
Fields = Fields?.Select(f => f.ToCipherFieldData()),
|
||||||
|
PasswordHistory = PasswordHistory?.Select(ph => ph.ToCipherPasswordHistoryData()),
|
||||||
|
|
||||||
|
PrivateKey = SSHKey.PrivateKey,
|
||||||
|
PublicKey = SSHKey.PublicKey,
|
||||||
|
KeyFingerprint = SSHKey.KeyFingerprint,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CipherWithIdRequestModel : CipherRequestModel
|
public class CipherWithIdRequestModel : CipherRequestModel
|
||||||
|
@ -48,6 +48,12 @@ public class CipherMiniResponseModel : ResponseModel
|
|||||||
cipherData = identityData;
|
cipherData = identityData;
|
||||||
Identity = new CipherIdentityModel(identityData);
|
Identity = new CipherIdentityModel(identityData);
|
||||||
break;
|
break;
|
||||||
|
case CipherType.SSHKey:
|
||||||
|
var sshKeyData = JsonSerializer.Deserialize<CipherSSHKeyData>(cipher.Data);
|
||||||
|
Data = sshKeyData;
|
||||||
|
cipherData = sshKeyData;
|
||||||
|
SSHKey = new CipherSSHKeyModel(sshKeyData);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException("Unsupported " + nameof(Type) + ".");
|
throw new ArgumentException("Unsupported " + nameof(Type) + ".");
|
||||||
}
|
}
|
||||||
@ -76,6 +82,7 @@ public class CipherMiniResponseModel : ResponseModel
|
|||||||
public CipherCardModel Card { get; set; }
|
public CipherCardModel Card { get; set; }
|
||||||
public CipherIdentityModel Identity { get; set; }
|
public CipherIdentityModel Identity { get; set; }
|
||||||
public CipherSecureNoteModel SecureNote { get; set; }
|
public CipherSecureNoteModel SecureNote { get; set; }
|
||||||
|
public CipherSSHKeyModel SSHKey { get; set; }
|
||||||
public IEnumerable<CipherFieldModel> Fields { get; set; }
|
public IEnumerable<CipherFieldModel> Fields { get; set; }
|
||||||
public IEnumerable<CipherPasswordHistoryModel> PasswordHistory { get; set; }
|
public IEnumerable<CipherPasswordHistoryModel> PasswordHistory { get; set; }
|
||||||
public IEnumerable<AttachmentResponseModel> Attachments { get; set; }
|
public IEnumerable<AttachmentResponseModel> Attachments { get; set; }
|
||||||
|
@ -22,6 +22,7 @@ public static class Constants
|
|||||||
public const int OrganizationSelfHostSubscriptionGracePeriodDays = 60;
|
public const int OrganizationSelfHostSubscriptionGracePeriodDays = 60;
|
||||||
|
|
||||||
public const string Fido2KeyCipherMinimumVersion = "2023.10.0";
|
public const string Fido2KeyCipherMinimumVersion = "2023.10.0";
|
||||||
|
public const string SSHKeyCipherMinimumVersion = "2024.12.0";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used by IdentityServer to identify our own provider.
|
/// Used by IdentityServer to identify our own provider.
|
||||||
@ -122,6 +123,8 @@ public static class FeatureFlagKeys
|
|||||||
public const string InlineMenuPositioningImprovements = "inline-menu-positioning-improvements";
|
public const string InlineMenuPositioningImprovements = "inline-menu-positioning-improvements";
|
||||||
public const string ProviderClientVaultPrivacyBanner = "ac-2833-provider-client-vault-privacy-banner";
|
public const string ProviderClientVaultPrivacyBanner = "ac-2833-provider-client-vault-privacy-banner";
|
||||||
public const string DeviceTrustLogging = "pm-8285-device-trust-logging";
|
public const string DeviceTrustLogging = "pm-8285-device-trust-logging";
|
||||||
|
public const string SSHKeyItemVaultItem = "ssh-key-vault-item";
|
||||||
|
public const string SSHAgent = "ssh-agent";
|
||||||
public const string AuthenticatorTwoFactorToken = "authenticator-2fa-token";
|
public const string AuthenticatorTwoFactorToken = "authenticator-2fa-token";
|
||||||
public const string EnableUpgradePasswordManagerSub = "AC-2708-upgrade-password-manager-sub";
|
public const string EnableUpgradePasswordManagerSub = "AC-2708-upgrade-password-manager-sub";
|
||||||
public const string IdpAutoSubmitLogin = "idp-auto-submit-login";
|
public const string IdpAutoSubmitLogin = "idp-auto-submit-login";
|
||||||
|
@ -8,4 +8,5 @@ public enum CipherType : byte
|
|||||||
SecureNote = 2,
|
SecureNote = 2,
|
||||||
Card = 3,
|
Card = 3,
|
||||||
Identity = 4,
|
Identity = 4,
|
||||||
|
SSHKey = 5,
|
||||||
}
|
}
|
||||||
|
10
src/Core/Vault/Models/Data/CipherSSHKeyData.cs
Normal file
10
src/Core/Vault/Models/Data/CipherSSHKeyData.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Bit.Core.Vault.Models.Data;
|
||||||
|
|
||||||
|
public class CipherSSHKeyData : CipherData
|
||||||
|
{
|
||||||
|
public CipherSSHKeyData() { }
|
||||||
|
|
||||||
|
public string PrivateKey { get; set; }
|
||||||
|
public string PublicKey { get; set; }
|
||||||
|
public string KeyFingerprint { get; set; }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user