Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BEEEP][SM-893] Add the ability to run SM integration tests as a service account #3187

Merged
merged 14 commits into from Mar 29, 2024
Merged
9 changes: 9 additions & 0 deletions test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs
Expand Up @@ -64,4 +64,13 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
SqliteConnection.Dispose();
}

/// <summary>
/// Helper for logging in via client secret.
/// Currently used for Secrets Manager service accounts
/// </summary>
public async Task<string> LoginWithClientSecretAsync(Guid clientId, string clientSecret)
{
return await _identityApplicationFactory.TokenFromAccessTokenAsync(clientId, clientSecret);
}
}

Large diffs are not rendered by default.

@@ -1,7 +1,7 @@
using System.Net;
using System.Net.Http.Headers;
using Bit.Api.IntegrationTest.Factories;
using Bit.Api.IntegrationTest.SecretsManager.Enums;
using Bit.Api.IntegrationTest.SecretsManager.Helpers;
using Bit.Api.Models.Response;
using Bit.Api.SecretsManager.Models.Request;
using Bit.Api.SecretsManager.Models.Response;
Expand All @@ -10,7 +10,6 @@
using Bit.Core.SecretsManager.Entities;
using Bit.Core.SecretsManager.Repositories;
using Bit.Test.Common.Helpers;
using Pipelines.Sockets.Unofficial.Arenas;
using Xunit;

namespace Bit.Api.IntegrationTest.SecretsManager.Controllers;
Expand All @@ -24,6 +23,7 @@ public class ProjectsControllerTests : IClassFixture<ApiApplicationFactory>, IAs
private readonly ApiApplicationFactory _factory;
private readonly IProjectRepository _projectRepository;
private readonly IAccessPolicyRepository _accessPolicyRepository;
private readonly LoginHelper _loginHelper;

private string _email = null!;
private SecretsManagerOrganizationHelper _organizationHelper = null!;
Expand All @@ -34,6 +34,7 @@ public ProjectsControllerTests(ApiApplicationFactory factory)
_client = _factory.CreateClient();
_projectRepository = _factory.GetService<IProjectRepository>();
_accessPolicyRepository = _factory.GetService<IAccessPolicyRepository>();
_loginHelper = new LoginHelper(_factory, _client);
}

public async Task InitializeAsync()
Expand All @@ -49,12 +50,6 @@ public Task DisposeAsync()
return Task.CompletedTask;
}

private async Task LoginAsync(string email)
{
var tokens = await _factory.LoginAsync(email);
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token);
}

[Theory]
[InlineData(false, false, false)]
[InlineData(false, false, true)]
Expand All @@ -66,7 +61,7 @@ private async Task LoginAsync(string email)
public async Task ListByOrganization_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled)
{
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var response = await _client.GetAsync($"/organizations/{org.Id}/projects");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
Expand All @@ -77,7 +72,7 @@ public async Task ListByOrganization_UserWithoutPermission_EmptyList()
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

await CreateProjectsAsync(org.Id);

Expand All @@ -86,7 +81,7 @@ public async Task ListByOrganization_UserWithoutPermission_EmptyList()

var result = await response.Content.ReadFromJsonAsync<ListResponseModel<ProjectResponseModel>>();
Assert.NotNull(result);
Assert.Empty(result!.Data);
Assert.Empty(result.Data);
}

[Theory]
Expand All @@ -101,7 +96,7 @@ public async Task ListByOrganization_Success(PermissionType permissionType)

var result = await response.Content.ReadFromJsonAsync<ListResponseModel<ProjectResponseModel>>();
Assert.NotNull(result);
Assert.NotEmpty(result!.Data);
Assert.NotEmpty(result.Data);
Assert.Equal(projectIds.Count, result.Data.Count());
}

Expand All @@ -116,7 +111,7 @@ public async Task ListByOrganization_Success(PermissionType permissionType)
public async Task Create_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled)
{
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var request = new ProjectCreateRequestModel { Name = _mockEncryptedString };

Expand All @@ -129,7 +124,7 @@ public async Task Create_SmAccessDenied_NotFound(bool useSecrets, bool accessSec
[InlineData(PermissionType.RunAsUserWithPermission)]
public async Task Create_AtMaxProjects_BadRequest(PermissionType permissionType)
{
var (_, organization) = await SetupProjectsWithAccessAsync(permissionType, 3);
var (_, organization) = await SetupProjectsWithAccessAsync(permissionType);
var request = new ProjectCreateRequestModel { Name = _mockEncryptedString };

var response = await _client.PostAsJsonAsync($"/organizations/{organization.Id}/projects", request);
Expand All @@ -143,14 +138,14 @@ public async Task Create_AtMaxProjects_BadRequest(PermissionType permissionType)
public async Task Create_Success(PermissionType permissionType)
{
var (org, adminOrgUser) = await _organizationHelper.Initialize(true, true, true);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);
var orgUserId = adminOrgUser.Id;
var currentUserId = adminOrgUser.UserId!.Value;

if (permissionType == PermissionType.RunAsUserWithPermission)
{
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);
orgUserId = orgUser.Id;
currentUserId = orgUser.UserId!.Value;
}
Expand All @@ -162,7 +157,7 @@ public async Task Create_Success(PermissionType permissionType)
var result = await response.Content.ReadFromJsonAsync<ProjectResponseModel>();

Assert.NotNull(result);
Assert.Equal(request.Name, result!.Name);
Assert.Equal(request.Name, result.Name);
AssertHelper.AssertRecent(result.RevisionDate);
AssertHelper.AssertRecent(result.CreationDate);

Expand Down Expand Up @@ -196,7 +191,7 @@ public async Task Create_Success(PermissionType permissionType)
public async Task Update_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled)
{
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var initialProject = await _projectRepository.CreateAsync(new Project
{
Expand Down Expand Up @@ -244,7 +239,7 @@ public async Task Update_Success(PermissionType permissionType)
public async Task Update_NonExistingProject_NotFound()
{
await _organizationHelper.Initialize(true, true, true);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var request = new ProjectUpdateRequestModel
{
Expand All @@ -262,7 +257,7 @@ public async Task Update_MissingAccessPolicy_NotFound()
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var project = await _projectRepository.CreateAsync(new Project
{
Expand Down Expand Up @@ -292,7 +287,7 @@ public async Task Update_MissingAccessPolicy_NotFound()
public async Task Get_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled)
{
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var project = await _projectRepository.CreateAsync(new Project
{
Expand All @@ -313,7 +308,7 @@ public async Task Get_MissingAccessPolicy_NotFound()
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var createdProject = await _projectRepository.CreateAsync(new Project
{
Expand All @@ -330,15 +325,15 @@ public async Task Get_NonExistingProject_NotFound()
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var createdProject = await _projectRepository.CreateAsync(new Project
{
OrganizationId = org.Id,
Name = _mockEncryptedString,
});

var deleteResponse = await _client.PostAsync("/projects/delete", JsonContent.Create(createdProject.Id));
await _client.PostAsync("/projects/delete", JsonContent.Create(createdProject.Id));

var response = await _client.GetAsync($"/projects/{createdProject.Id}");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
Expand Down Expand Up @@ -372,7 +367,7 @@ public async Task Get_Success(PermissionType permissionType)
public async Task Delete_SmAccessDenied_NotFound(bool useSecrets, bool accessSecrets, bool organizationEnabled)
{
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets, organizationEnabled);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var projectIds = await CreateProjectsAsync(org.Id);

Expand All @@ -385,7 +380,7 @@ public async Task Delete_MissingAccessPolicy_AccessDenied()
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var projectIds = await CreateProjectsAsync(org.Id);

Expand All @@ -394,7 +389,7 @@ public async Task Delete_MissingAccessPolicy_AccessDenied()
var results = await response.Content.ReadFromJsonAsync<ListResponseModel<BulkDeleteResponseModel>>();
Assert.NotNull(results);
Assert.Equal(projectIds.OrderBy(x => x),
results!.Data.Select(x => x.Id).OrderBy(x => x));
results.Data.Select(x => x.Id).OrderBy(x => x));
Assert.All(results.Data, item => Assert.Equal("access denied", item.Error));
}

Expand All @@ -411,7 +406,7 @@ public async Task Delete_Success(PermissionType permissionType)
var results = await response.Content.ReadFromJsonAsync<ListResponseModel<BulkDeleteResponseModel>>();
Assert.NotNull(results);
Assert.Equal(projectIds.OrderBy(x => x),
results!.Data.Select(x => x.Id).OrderBy(x => x));
results.Data.Select(x => x.Id).OrderBy(x => x));
Assert.DoesNotContain(results.Data, x => x.Error != null);

var projects = await _projectRepository.GetManyWithSecretsByIds(projectIds);
Expand All @@ -438,7 +433,7 @@ private async Task<List<Guid>> CreateProjectsAsync(Guid orgId, int numberToCreat
int projectsToCreate = 3)
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);
var projectIds = await CreateProjectsAsync(org.Id, projectsToCreate);

if (permissionType == PermissionType.RunAsAdmin)
Expand All @@ -447,7 +442,7 @@ private async Task<List<Guid>> CreateProjectsAsync(Guid orgId, int numberToCreat
}

var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var accessPolicies = projectIds.Select(projectId => new UserProjectAccessPolicy
{
Expand All @@ -467,7 +462,7 @@ private async Task<List<Guid>> CreateProjectsAsync(Guid orgId, int numberToCreat
private async Task<Project> SetupProjectWithAccessAsync(PermissionType permissionType)
{
var (org, _) = await _organizationHelper.Initialize(true, true, true);
await LoginAsync(_email);
await _loginHelper.LoginAsync(_email);

var initialProject = await _projectRepository.CreateAsync(new Project
{
Expand All @@ -481,7 +476,7 @@ private async Task<Project> SetupProjectWithAccessAsync(PermissionType permissio
}

var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
await LoginAsync(email);
await _loginHelper.LoginAsync(email);

var accessPolicies = new List<BaseAccessPolicy>
{
Expand Down