Skip to content

Commit

Permalink
chore(sonar): fix code-scanner findings #437 (#531)
Browse files Browse the repository at this point in the history
* chore(user): remove obsolete endpoints
* remove GET /api/user/app/{appId}/roles
* remove PUT /api/user/app/{appId}/roles
* chore(identityprovider): remove obsolete endpoint
* remove POST /api/identityprovider/owncompany/users/{companyUserId}/identityprovider
* core(sonar): fix trivial findings
* chore(sonar): add null checks to handling of keycloak-reponse-data
* chore(codeql): fix codeql findings
* chore(codeql): fix encryption findings
* chore(encryption) use CipherMode.CBC instead of CFB
* chore(framework) update minor version to 1.2.0
* add example config to application.json
  • Loading branch information
ntruchsess authored Mar 6, 2024
1 parent 3377db8 commit 0e26043
Show file tree
Hide file tree
Showing 216 changed files with 11,343 additions and 2,552 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -472,7 +471,7 @@ public async Task ApproveCredential(Guid credentialId, CancellationToken cancell
throw new ConflictException("The VerifiedCredentialExternalTypeUseCaseDetail must be set");
}

var typeValue = data.Type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {data.Type.ToString()} does not exists");
var typeValue = data.Type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {data.Type} does not exists");
var content = JsonSerializer.Serialize(new { Type = data.Type, CredentialId = credentialId }, Options);
_portalRepositories.GetInstance<INotificationRepository>().CreateNotification(data.RequesterData.RequesterId, NotificationTypeId.CREDENTIAL_APPROVAL, false, n =>
{
Expand Down Expand Up @@ -540,7 +539,7 @@ public async Task RejectCredential(Guid credentialId)
throw new ConflictException($"Credential {credentialId} must be {CompanySsiDetailStatusId.PENDING}");
}

var typeValue = type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {type.ToString()} does not exists");
var typeValue = type.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {type} does not exists");
var content = JsonSerializer.Serialize(new { Type = type, CredentialId = credentialId }, Options);
_portalRepositories.GetInstance<INotificationRepository>().CreateNotification(requesterId, NotificationTypeId.CREDENTIAL_REJECTED, false, n =>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -36,7 +35,6 @@ public interface IIdentityProviderBusinessLogic
IAsyncEnumerable<UserIdentityProviderData> GetOwnCompanyUsersIdentityProviderDataAsync(IEnumerable<Guid> identityProviderIds, bool unlinkedUsersOnly);
(Stream FileStream, string ContentType, string FileName, Encoding Encoding) GetOwnCompanyUsersIdentityProviderLinkDataStream(IEnumerable<Guid> identityProviderIds, bool unlinkedUsersOnly);
ValueTask<IdentityProviderUpdateStats> UploadOwnCompanyUsersIdentityProviderLinkDataAsync(IFormFile document, CancellationToken cancellationToken);
ValueTask<UserIdentityProviderLinkData> CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData);
ValueTask<UserIdentityProviderLinkData> CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData);
ValueTask<UserIdentityProviderLinkData> GetOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId);
ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid companyUserId, Guid identityProviderId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ public interface IPartnerNetworkBusinessLogic
/// Get all member activecompanies bpn
/// </summary>
/// <param name="bpnIds">Ids of BPN</param>
IAsyncEnumerable<string?> GetAllMemberCompaniesBPNAsync(IEnumerable<string>? bpnIds);
IAsyncEnumerable<string> GetAllMemberCompaniesBPNAsync(IEnumerable<string>? bpnIds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public interface IUserBusinessLogic
IAsyncEnumerable<string> CreateOwnCompanyUsersAsync(IEnumerable<UserCreationInfo> userList);
Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, UserCreationInfoIdp userCreationInfo);
Task<Pagination.Response<CompanyUserData>> GetOwnCompanyUserDatasAsync(int page, int size, GetOwnCompanyUsersFilter filter);
[Obsolete("to be replaced by UserRolesBusinessLogic.GetAppRolesAsync. Remove as soon frontend is adjusted")]
IAsyncEnumerable<ClientRoles> GetClientRolesAsync(Guid appId, string? languageShortName = null);
Task<CompanyUserDetailData> GetOwnCompanyUserDetailsAsync(Guid userId);
Task<int> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid userId, IEnumerable<string> businessPartnerNumbers);
Task<int> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid userId, string businessPartnerNumber);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -45,13 +44,4 @@ public interface IUserRolesBusinessLogic
/// <param name="roles"></param>
/// <returns>messages</returns>
Task<IEnumerable<UserRoleWithId>> ModifyAppUserRolesAsync(Guid appId, Guid companyUserId, IEnumerable<string> roles);

/// <summary>
/// Update Role to User
/// </summary>
/// <param name="appId">app Id</param>
/// <param name="userRoleInfo">User and Role Information like CompanyUser Id and Role Name</param>
/// <returns>messages</returns>
[Obsolete("to be replaced by endpoint UserRolesBusinessLogic.ModifyAppUserRolesAsync. Remove as soon frontend is adjusted")]
Task<IEnumerable<UserRoleWithId>> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo);
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private async ValueTask<IdentityProviderDetails> CreateOwnCompanyIdentityProvide
{
IamIdentityProviderProtocol.OIDC => await GetIdentityProviderDetailsOidc(identityProviderId, alias, IdentityProviderCategoryId.KEYCLOAK_OIDC, typeId, null).ConfigureAwait(false),
IamIdentityProviderProtocol.SAML => await GetIdentityProviderDetailsSaml(identityProviderId, alias, typeId).ConfigureAwait(false),
_ => throw new UnexpectedConditionException($"unexpected value of protocol: '{protocol.ToString()}'")
_ => throw new UnexpectedConditionException($"unexpected value of protocol: '{protocol}'")
};
}

Expand Down Expand Up @@ -268,7 +268,7 @@ public async ValueTask<IdentityProviderDetails> UpdateOwnCompanyIdentityProvider
await UpdateIdentityProviderSaml(alias, details).ConfigureAwait(false);
return await GetIdentityProviderDetailsSaml(identityProviderId, alias, typeId).ConfigureAwait(false);
default:
throw new ControllerArgumentException($"unexpected value for category '{category.ToString()}' of identityProvider '{identityProviderId}'");
throw new ControllerArgumentException($"unexpected value for category '{category}' of identityProvider '{identityProviderId}'");
}
}

Expand Down Expand Up @@ -587,32 +587,6 @@ private async ValueTask<IdentityProviderDetails> GetIdentityProviderDetailsSaml(
};
}

public async ValueTask<UserIdentityProviderLinkData> CreateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, UserIdentityProviderLinkData identityProviderLinkData)
{
var companyId = _identityData.CompanyId;
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderLinkData.identityProviderId, companyId).ConfigureAwait(false);

try
{
await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
iamUserId,
new IdentityProviderLink(
alias,
identityProviderLinkData.userId,
identityProviderLinkData.userName))
.ConfigureAwait(false);
}
catch (KeycloakEntityConflictException ce)
{
throw new ConflictException($"identityProviderLink for identityProvider {identityProviderLinkData.identityProviderId} already exists for user {companyUserId}", ce);
}

return new UserIdentityProviderLinkData(
identityProviderLinkData.identityProviderId,
identityProviderLinkData.userId,
identityProviderLinkData.userName);
}

public async ValueTask<UserIdentityProviderLinkData> CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(Guid companyUserId, Guid identityProviderId, UserLinkData userLinkData)
{
var companyId = _identityData.CompanyId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ await data.ValidateDatabaseData(
},
out var idpAliasDataTask)
? await idpAliasDataTask!.ConfigureAwait(false)
: (IDictionary<Guid, string>?)null;
: default(IDictionary<Guid, string>?);

var idpIds = idpAliase?.Keys ?? Enumerable.Empty<Guid>();
var allIdpIds = singleIdpAlias == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ public PartnerNetworkBusinessLogic(IPortalRepositories portalRepositories)
}

/// <inheritdoc/>
public IAsyncEnumerable<string?> GetAllMemberCompaniesBPNAsync(IEnumerable<string>? bpnIds) =>
_portalRepositories.GetInstance<ICompanyRepository>().GetAllMemberCompaniesBPNAsync(bpnIds);
public IAsyncEnumerable<string> GetAllMemberCompaniesBPNAsync(IEnumerable<string>? bpnIds) =>
_portalRepositories.GetInstance<ICompanyRepository>().GetAllMemberCompaniesBPNAsync(bpnIds?.Select(x => x.ToUpper()));
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@

using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Encryption;
using Org.Eclipse.TractusX.Portal.Backend.OnboardingServiceProvider.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
using System.Security.Cryptography;
using System.Text;

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;

Expand Down Expand Up @@ -60,40 +59,33 @@ public async Task SetCallbackAddress(OnboardingServiceProviderCallbackRequestDat
throw new ForbiddenException($"Only {CompanyRoleId.ONBOARDING_SERVICE_PROVIDER} are allowed to set the callback url");
}

using var aes = Aes.Create();
aes.Key = Encoding.UTF8.GetBytes(_settings.EncryptionKey);
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (var memoryStream = new MemoryStream())
var cryptoConfig = _settings.EncryptionConfigs.SingleOrDefault(x => x.Index == _settings.EncrptionConfigIndex) ?? throw new ConfigurationException($"EncryptionModeIndex {_settings.EncrptionConfigIndex} is not configured");
var (secret, initializationVector) = CryptoHelper.Encrypt(requestData.ClientSecret, Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode);

if (ospDetails != null)
{
companyRepository.AttachAndModifyOnboardingServiceProvider(companyId, osp =>
{
osp.CallbackUrl = ospDetails.CallbackUrl;
osp.AuthUrl = ospDetails.AuthUrl;
osp.ClientId = ospDetails.ClientId;
osp.ClientSecret = ospDetails.ClientSecret;
osp.EncryptionMode = ospDetails.EncryptionMode;
osp.InitializationVector = ospDetails.InitializationVector;
},
osp =>
{
osp.CallbackUrl = requestData.CallbackUrl;
osp.AuthUrl = requestData.AuthUrl;
osp.ClientId = requestData.ClientId;
osp.ClientSecret = secret;
osp.EncryptionMode = cryptoConfig.Index;
osp.InitializationVector = initializationVector;
});
}
else
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using var sw = new StreamWriter(cryptoStream, Encoding.UTF8);
sw.Write(requestData.ClientSecret);
}
var secret = memoryStream.ToArray();
if (ospDetails != null)
{
companyRepository.AttachAndModifyOnboardingServiceProvider(companyId, osp =>
{
osp.CallbackUrl = ospDetails.CallbackUrl;
osp.AuthUrl = ospDetails.AuthUrl;
osp.ClientId = ospDetails.ClientId;
osp.ClientSecret = secret;
},
osp =>
{
osp.CallbackUrl = requestData.CallbackUrl;
osp.AuthUrl = requestData.AuthUrl;
osp.ClientId = requestData.ClientId;
osp.ClientSecret = secret;
});
}
else
{
companyRepository.CreateOnboardingServiceProviderDetails(companyId, requestData.CallbackUrl, requestData.AuthUrl, requestData.ClientId, secret);
}
companyRepository.CreateOnboardingServiceProviderDetails(companyId, requestData.CallbackUrl, requestData.AuthUrl, requestData.ClientId, secret, initializationVector, cryptoConfig.Index);
}
await _portalRepositories.SaveAsync().ConfigureAwait(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ private async IAsyncEnumerable<string> CreateOwnCompanyUsersInternalAsync(IEnume

var companyDisplayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(false);

await foreach (var (_, userName, password, error) in _userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps).ConfigureAwait(false))
await foreach (var (companyUserId, userName, password, error) in _userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps).ConfigureAwait(false))
{
var email = emailData[userName];

if (error != null)
{
_logger.LogError(error, "Error while creating user {UserName} ({Email})", userName, email);
_logger.LogError(error, "Error while creating user {companyUserId}", companyUserId);
continue;
}

Expand All @@ -148,7 +148,7 @@ private async IAsyncEnumerable<string> CreateOwnCompanyUsersInternalAsync(IEnume
}
catch (Exception e)
{
_logger.LogError(e, "Error sending email to {Email} after creating user {UserName}", email, userName);
_logger.LogError(e, "Error sending email after creating user {companyUserId}", companyUserId);
}

yield return email;
Expand Down Expand Up @@ -220,7 +220,7 @@ public async Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, Us
}
catch (Exception e)
{
_logger.LogError(e, "Error sending email to {Email} after creating user {UserName}", userCreationInfo.Email, userCreationInfo.UserName);
_logger.LogError(e, "Error sending email after creating user {CompanyUserId}", result.CompanyUserId);
}

return result.CompanyUserId;
Expand Down Expand Up @@ -272,26 +272,6 @@ public async Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, Us

private async Task<string> GetDisplayName(string alias) => await _provisioningManager.GetIdentityProviderDisplayName(alias).ConfigureAwait(false) ?? throw new ConflictException($"Display Name should not be null for alias: {alias}");

[Obsolete("to be replaced by UserRolesBusinessLogic.GetAppRolesAsync. Remove as soon frontend is adjusted")]
public async IAsyncEnumerable<ClientRoles> GetClientRolesAsync(Guid appId, string? languageShortName = null)
{
var appRepository = _portalRepositories.GetInstance<IOfferRepository>();
if (!await appRepository.CheckAppExistsById(appId).ConfigureAwait(false))
{
throw new NotFoundException($"app {appId} does not found");
}

if (languageShortName != null && !await _portalRepositories.GetInstance<ILanguageRepository>().IsValidLanguageCode(languageShortName))
{
throw new ArgumentException($"language {languageShortName} does not exist");
}

await foreach (var roles in appRepository.GetClientRolesAsync(appId, languageShortName ?? Constants.DefaultLanguage).ConfigureAwait(false))
{
yield return new ClientRoles(roles.RoleId, roles.Role, roles.Description);
}
}

public async Task<CompanyUserDetailData> GetOwnCompanyUserDetailsAsync(Guid userId)
{
var companyId = _identityData.CompanyId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,6 @@ public Task<IEnumerable<UserRoleWithId>> ModifyAppUserRolesAsync(Guid appId, Gui
}, _options), NotificationTypeId.ROLE_UPDATE_APP_OFFER);
});

[Obsolete("to be replaced by endpoint UserRolesBusinessLogic.ModifyAppUserRolesAsync. Remove as soon frontend is adjusted")]
public Task<IEnumerable<UserRoleWithId>> ModifyUserRoleAsync(Guid appId, UserRoleInfo userRoleInfo) =>
ModifyUserRolesInternal(
() => _portalRepositories.GetInstance<IUserRepository>()
.GetAppAssignedIamClientUserDataUntrackedAsync(appId, userRoleInfo.CompanyUserId, _identityData.CompanyId),
(Guid companyUserId, IEnumerable<string> roles, Guid offerId) => _portalRepositories.GetInstance<IUserRolesRepository>()
.GetAssignedAndMatchingAppRoles(companyUserId, roles, offerId).Select(x => new UserRoleModificationData(x.UserRoleText, x.RoleId, x.IsAssigned, true)),
appId, userRoleInfo.CompanyUserId, userRoleInfo.Roles, _identityData.CompanyId, null);

private async Task<IEnumerable<UserRoleWithId>> ModifyUserRolesInternal(
Func<Task<OfferIamUserData?>> getIamUserData,
Func<Guid, IEnumerable<string>, Guid, IAsyncEnumerable<UserRoleModificationData>> getUserRoleModificationData,
Expand Down Expand Up @@ -211,13 +202,14 @@ await _provisioningManager.AssignClientRolesToCentralUserAsync(iamUserId, client
// Assign the roles in keycloak, check if all roles were added foreach client, if not throw an exception with the client and the roles that were not assigned.
.Select(assigned => (
Client: assigned.Client,
UnassingedRoles: rolesToAdd.ExceptBy(assigned.Roles, toAdd => toAdd.CompanyUserRoleText)))
UnassingedRoles: rolesToAdd.ExceptBy(assigned.Roles, toAdd => toAdd.CompanyUserRoleText),
Error: assigned.Error))
.Where(x => x.UnassingedRoles.Any())
.IfAny(async unassigned =>
throw new ServiceException($"The following roles could not be added to the clients: \n {string.Join(
"\n",
await unassigned
.Select(item => $"Client: {item.Client}, Roles: {string.Join(", ", item.UnassingedRoles.Select(r => r.CompanyUserRoleText))}")
.Select(item => $"Client: {item.Client}, Roles: {string.Join(", ", item.UnassingedRoles.Select(r => r.CompanyUserRoleText))}, Error: {item.Error?.Message}")
.ToListAsync()
.ConfigureAwait(false))}"))
.ConfigureAwait(false);
Expand Down
Loading

0 comments on commit 0e26043

Please sign in to comment.