mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 07:36:14 -05:00
[SM-429] Add permission checks to access policy endpoints (#2628)
* Add permission checks to access policy endpoints * Fix unit tests * Add service account grant permission checks * Add service account grant tests * Add new endpoint unit tests * Cleanup unit tests add integration tests * User permission enum in create tests * Swap to NotFoundException for access checks * Add filter for potential grantees * Add in AccessSecretsManager check and test it * Add code review updates * Code review updates * Refactor potential grantees endpoint * Code review updates
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using Bit.Api.IntegrationTest.Factories;
|
||||
using Bit.Api.IntegrationTest.Helpers;
|
||||
using Bit.Api.IntegrationTest.SecretsManager.Enums;
|
||||
using Bit.Api.Models.Response;
|
||||
using Bit.Api.SecretsManager.Models.Request;
|
||||
using Bit.Api.SecretsManager.Models.Response;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Bit.Test.Common.Helpers;
|
||||
@ -13,16 +15,17 @@ namespace Bit.Api.IntegrationTest.SecretsManager.Controllers;
|
||||
|
||||
public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>, IAsyncLifetime
|
||||
{
|
||||
private const string _mockEncryptedString =
|
||||
"2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98sp4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg=";
|
||||
|
||||
private readonly IAccessPolicyRepository _accessPolicyRepository;
|
||||
|
||||
private readonly HttpClient _client;
|
||||
private readonly ApiApplicationFactory _factory;
|
||||
|
||||
private const string _mockEncryptedString = "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98sp4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg=";
|
||||
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly IServiceAccountRepository _serviceAccountRepository;
|
||||
private Organization _organization = null!;
|
||||
private string _email = null!;
|
||||
private SecretsManagerOrganizationHelper _organizationHelper = null!;
|
||||
|
||||
public AccessPoliciesControllerTest(ApiApplicationFactory factory)
|
||||
{
|
||||
@ -35,46 +38,105 @@ public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
var ownerEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com";
|
||||
var tokens = await _factory.LoginWithNewAccount(ownerEmail);
|
||||
var (organization, _) =
|
||||
await OrganizationTestHelpers.SignUpAsync(_factory, ownerEmail: ownerEmail, billingEmail: ownerEmail);
|
||||
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token);
|
||||
_organization = organization;
|
||||
_email = $"integration-test{Guid.NewGuid()}@bitwarden.com";
|
||||
await _factory.LoginWithNewAccount(_email);
|
||||
_organizationHelper = new SecretsManagerOrganizationHelper(_factory, _email);
|
||||
}
|
||||
|
||||
public Task DisposeAsync() => Task.CompletedTask;
|
||||
|
||||
[Fact]
|
||||
public async Task CreateProjectAccessPolicies()
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
var initialProject = await _projectRepository.CreateAsync(new Project
|
||||
_client.Dispose();
|
||||
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)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task CreateProjectAccessPolicies_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
{
|
||||
OrganizationId = _organization.Id,
|
||||
Name = _mockEncryptedString
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var initialServiceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = _organization.Id,
|
||||
Name = _mockEncryptedString
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var request = new AccessPoliciesCreateRequest
|
||||
{
|
||||
ServiceAccountAccessPolicyRequests = new List<AccessPolicyRequest>
|
||||
{
|
||||
new() { GranteeId = initialServiceAccount.Id, Read = true, Write = true }
|
||||
}
|
||||
new() { GranteeId = serviceAccount.Id, Read = true, Write = true },
|
||||
},
|
||||
};
|
||||
|
||||
var response = await _client.PostAsJsonAsync($"/projects/{initialProject.Id}/access-policies", request);
|
||||
var response = await _client.PostAsJsonAsync($"/projects/{project.Id}/access-policies", request);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task CreateProjectAccessPolicies(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
var accessPolicies = new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserProjectAccessPolicy
|
||||
{
|
||||
GrantedProjectId = project.Id, OrganizationUserId = orgUser.Id, Read = true, Write = true,
|
||||
},
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
}
|
||||
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var request = new AccessPoliciesCreateRequest
|
||||
{
|
||||
ServiceAccountAccessPolicyRequests = new List<AccessPolicyRequest>
|
||||
{
|
||||
new() { GranteeId = serviceAccount.Id, Read = true, Write = true },
|
||||
},
|
||||
};
|
||||
|
||||
var response = await _client.PostAsJsonAsync($"/projects/{project.Id}/access-policies", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ProjectAccessPoliciesResponseModel>();
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(initialServiceAccount.Id, result!.ServiceAccountAccessPolicies.First().ServiceAccountId);
|
||||
Assert.Equal(serviceAccount.Id, result!.ServiceAccountAccessPolicies.First().ServiceAccountId);
|
||||
Assert.True(result.ServiceAccountAccessPolicies.First().Read);
|
||||
Assert.True(result.ServiceAccountAccessPolicies.First().Write);
|
||||
AssertHelper.AssertRecent(result.ServiceAccountAccessPolicies.First().RevisionDate);
|
||||
@ -91,15 +153,103 @@ public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAccessPolicy()
|
||||
public async Task CreateProjectAccessPolicies_NoPermission()
|
||||
{
|
||||
var initData = await SetupAccessPolicyRequest();
|
||||
// Create a new account as a user
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var request = new AccessPoliciesCreateRequest
|
||||
{
|
||||
ServiceAccountAccessPolicyRequests = new List<AccessPolicyRequest>
|
||||
{
|
||||
new() { GranteeId = serviceAccount.Id, Read = true, Write = true },
|
||||
},
|
||||
};
|
||||
|
||||
var response = await _client.PostAsJsonAsync($"/projects/{project.Id}/access-policies", request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task UpdateAccessPolicy_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
const bool expectedRead = true;
|
||||
const bool expectedWrite = false;
|
||||
var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite };
|
||||
|
||||
var response = await _client.PutAsJsonAsync($"/access-policies/{initData.InitialAccessPolicyId}", request);
|
||||
var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAccessPolicy_NoPermission()
|
||||
{
|
||||
// Create a new account as a user
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId);
|
||||
|
||||
const bool expectedRead = true;
|
||||
const bool expectedWrite = false;
|
||||
var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite };
|
||||
|
||||
var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task UpdateAccessPolicy(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
var accessPolicies = new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserProjectAccessPolicy
|
||||
{
|
||||
GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true,
|
||||
},
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
}
|
||||
|
||||
const bool expectedRead = true;
|
||||
const bool expectedWrite = false;
|
||||
var request = new AccessPolicyUpdateRequest { Read = expectedRead, Write = expectedWrite };
|
||||
|
||||
var response = await _client.PutAsJsonAsync($"/access-policies/{initData.AccessPolicyId}", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ServiceAccountProjectAccessPolicyResponseModel>();
|
||||
@ -116,29 +266,78 @@ public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>
|
||||
AssertHelper.AssertRecent(updatedAccessPolicy.RevisionDate);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task DeleteAccessPolicy_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}");
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAccessPolicy()
|
||||
public async Task DeleteAccessPolicy_NoPermission()
|
||||
{
|
||||
var initData = await SetupAccessPolicyRequest();
|
||||
// Create a new account as a user
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var response = await _client.DeleteAsync($"/access-policies/{initData.InitialAccessPolicyId}");
|
||||
var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId);
|
||||
|
||||
var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}");
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task DeleteAccessPolicy(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
var accessPolicies = new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserProjectAccessPolicy
|
||||
{
|
||||
GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true,
|
||||
},
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
}
|
||||
|
||||
var response = await _client.DeleteAsync($"/access-policies/{initData.AccessPolicyId}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var test = await _accessPolicyRepository.GetByIdAsync(initData.InitialAccessPolicyId);
|
||||
var test = await _accessPolicyRepository.GetByIdAsync(initData.AccessPolicyId);
|
||||
Assert.Null(test);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetProjectAccessPolicies_ReturnsEmpty()
|
||||
{
|
||||
var initialProject = await _projectRepository.CreateAsync(new Project
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
{
|
||||
OrganizationId = _organization.Id,
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var response = await _client.GetAsync($"/projects/{initialProject.Id}/access-policies");
|
||||
var response = await _client.GetAsync($"/projects/{project.Id}/access-policies");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ProjectAccessPoliciesResponseModel>();
|
||||
@ -149,12 +348,59 @@ public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>
|
||||
Assert.Empty(result!.ServiceAccountAccessPolicies);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetProjectAccessPolicies()
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task GetProjectAccessPolicies_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var initData = await SetupAccessPolicyRequest();
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
var response = await _client.GetAsync($"/projects/{initData.InitialProjectId}/access-policies");
|
||||
var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies");
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetProjectAccessPolicies_NoPermission()
|
||||
{
|
||||
// Create a new account as a user
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var initData = await SetupAccessPolicyRequest(orgUser.OrganizationId);
|
||||
|
||||
var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies");
|
||||
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task GetProjectAccessPolicies(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
var initData = await SetupAccessPolicyRequest(org.Id);
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
var accessPolicies = new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserProjectAccessPolicy
|
||||
{
|
||||
GrantedProjectId = initData.ProjectId, OrganizationUserId = orgUser.Id, Read = true, Write = true,
|
||||
},
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
}
|
||||
|
||||
var response = await _client.GetAsync($"/projects/{initData.ProjectId}/access-policies");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ProjectAccessPoliciesResponseModel>();
|
||||
@ -163,44 +409,166 @@ public class AccessPoliciesControllerTest : IClassFixture<ApiApplicationFactory>
|
||||
Assert.Single(result!.ServiceAccountAccessPolicies);
|
||||
}
|
||||
|
||||
private async Task<RequestSetupData> SetupAccessPolicyRequest()
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task GetPeoplePotentialGrantees_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var initialProject = await _projectRepository.CreateAsync(new Project
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var response =
|
||||
await _client.GetAsync(
|
||||
$"/organizations/{org.Id}/access-policies/people/potential-grantees");
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task GetPeoplePotentialGrantees_Success(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
OrganizationId = _organization.Id,
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
}
|
||||
|
||||
var response =
|
||||
await _client.GetAsync(
|
||||
$"/organizations/{org.Id}/access-policies/people/potential-grantees");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ListResponseModel<PotentialGranteeResponseModel>>();
|
||||
|
||||
Assert.NotNull(result?.Data);
|
||||
Assert.NotEmpty(result!.Data);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task GetServiceAccountPotentialGrantees_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var response =
|
||||
await _client.GetAsync(
|
||||
$"/organizations/{org.Id}/access-policies/service-accounts/potential-grantees");
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetServiceAccountPotentialGrantees_OnlyReturnsServiceAccountsWithWriteAccess()
|
||||
{
|
||||
// Create a new account as a user
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var initialServiceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
|
||||
var response =
|
||||
await _client.GetAsync(
|
||||
$"/organizations/{org.Id}/access-policies/service-accounts/potential-grantees");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ListResponseModel<PotentialGranteeResponseModel>>();
|
||||
|
||||
Assert.NotNull(result?.Data);
|
||||
Assert.Empty(result!.Data);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task GetServiceAccountsPotentialGrantees_Success(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = _organization.Id,
|
||||
OrganizationId = org.Id,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var initialAccessPolicy = await _accessPolicyRepository.CreateManyAsync(
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
await _accessPolicyRepository.CreateManyAsync(
|
||||
new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserServiceAccountAccessPolicy
|
||||
{
|
||||
GrantedServiceAccountId = serviceAccount.Id,
|
||||
OrganizationUserId = orgUser.Id,
|
||||
Read = true,
|
||||
Write = true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
var response =
|
||||
await _client.GetAsync(
|
||||
$"/organizations/{org.Id}/access-policies/service-accounts/potential-grantees");
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<ListResponseModel<PotentialGranteeResponseModel>>();
|
||||
|
||||
Assert.NotNull(result?.Data);
|
||||
Assert.NotEmpty(result!.Data);
|
||||
Assert.Equal(serviceAccount.Id.ToString(), result!.Data.First(x => x.Id == serviceAccount.Id.ToString()).Id);
|
||||
}
|
||||
|
||||
private async Task<RequestSetupData> SetupAccessPolicyRequest(Guid organizationId)
|
||||
{
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
{
|
||||
OrganizationId = organizationId,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount
|
||||
{
|
||||
OrganizationId = organizationId,
|
||||
Name = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var accessPolicy = await _accessPolicyRepository.CreateManyAsync(
|
||||
new List<BaseAccessPolicy>
|
||||
{
|
||||
new ServiceAccountProjectAccessPolicy
|
||||
{
|
||||
Read = true,
|
||||
Write = true,
|
||||
ServiceAccountId = initialServiceAccount.Id,
|
||||
GrantedProjectId = initialProject.Id,
|
||||
}
|
||||
Read = true, Write = true, ServiceAccountId = serviceAccount.Id, GrantedProjectId = project.Id,
|
||||
},
|
||||
});
|
||||
|
||||
return new RequestSetupData
|
||||
{
|
||||
InitialProjectId = initialProject.Id,
|
||||
InitialServiceAccountId = initialServiceAccount.Id,
|
||||
InitialAccessPolicyId = initialAccessPolicy.First().Id,
|
||||
ProjectId = project.Id,
|
||||
ServiceAccountId = serviceAccount.Id,
|
||||
AccessPolicyId = accessPolicy.First().Id,
|
||||
};
|
||||
}
|
||||
|
||||
private class RequestSetupData
|
||||
{
|
||||
public Guid InitialProjectId { get; set; }
|
||||
public Guid InitialAccessPolicyId { get; set; }
|
||||
public Guid InitialServiceAccountId { get; set; }
|
||||
public Guid ProjectId { get; set; }
|
||||
public Guid AccessPolicyId { get; set; }
|
||||
public Guid ServiceAccountId { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Api.IntegrationTest.SecretsManager.Enums;
|
||||
|
||||
public enum PermissionType
|
||||
{
|
||||
RunAsAdmin,
|
||||
RunAsUserWithPermission,
|
||||
}
|
Reference in New Issue
Block a user