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

[AC-2447] Update PutCollection to return Unavailable cipher when last Can Manage Access is Removed #4074

Merged
merged 8 commits into from May 21, 2024

Conversation

Jingo88
Copy link
Contributor

@Jingo88 Jingo88 commented May 10, 2024

- [ X ] Bug fix
- [ ] New feature development
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
- [ ] Build/deploy pipeline (DevOps)
- [ ] Other

Objective

When a user removes the final Can Manage access from a cipher, we will make their update request, and then return the cipher with an Unavailable value for the client to read

Screen Recording

AC-2447-Last-Can-Manage-Removed.mov

@Jingo88 Jingo88 requested a review from a team as a code owner May 10, 2024 18:12
@Jingo88 Jingo88 requested a review from gbubemismith May 10, 2024 18:12
Copy link

codecov bot commented May 10, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 39.14%. Comparing base (f224218) to head (d005093).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4074      +/-   ##
==========================================
+ Coverage   39.07%   39.14%   +0.06%     
==========================================
  Files        1201     1202       +1     
  Lines       58021    58045      +24     
  Branches     5339     5341       +2     
==========================================
+ Hits        22670    22719      +49     
+ Misses      34295    34265      -30     
- Partials     1056     1061       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

github-actions bot commented May 10, 2024

Logo
Checkmarx One – Scan Summary & Detailsea2e6748-8a21-438e-aa91-6b9361e5dfb0

New Issues

Severity Issue Source File / Package Checkmarx Insight
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 628 Attack Vector
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 628 Attack Vector
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 628 Attack Vector
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 628 Attack Vector
MEDIUM Privacy_Violation /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 343 Attack Vector
MEDIUM Privacy_Violation /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 396 Attack Vector
LOW Log_Forging /src/Api/Vault/Controllers/CiphersController.cs: 628 Attack Vector
LOW Log_Forging /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 308 Attack Vector
LOW Log_Forging /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 371 Attack Vector

Fixed Issues

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 607
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 607
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 607
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 607
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 132
MEDIUM CSRF /src/Api/AdminConsole/Controllers/ProvidersController.cs: 141
MEDIUM CSRF /src/Api/SecretsManager/Controllers/AccessPoliciesController.cs: 229
MEDIUM CSRF /src/Admin/AdminConsole/Controllers/ProvidersController.cs: 320
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 163
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 163
MEDIUM CSRF /src/Api/Billing/Controllers/ProviderClientsController.cs: 30
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 190
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 333
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 333
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 645
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 669
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 535
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 711
MEDIUM CSRF /src/Api/Vault/Controllers/FoldersController.cs: 45
MEDIUM CSRF /src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs: 51
MEDIUM CSRF /src/Api/Controllers/UsersController.cs: 22
MEDIUM CSRF /src/Api/Controllers/DevicesController.cs: 70
MEDIUM CSRF /src/Api/Controllers/DevicesController.cs: 57
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/PoliciesController.cs: 69
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/PoliciesController.cs: 49
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/OrganizationController.cs: 42
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/GroupsController.cs: 92
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/GroupsController.cs: 49
MEDIUM CSRF /src/Api/AdminConsole/Controllers/ProviderUsersController.cs: 142
MEDIUM CSRF /src/Api/AdminConsole/Controllers/PoliciesController.cs: 148
MEDIUM CSRF /src/Api/AdminConsole/Controllers/PoliciesController.cs: 78
MEDIUM CSRF /src/Api/AdminConsole/Controllers/PoliciesController.cs: 61
MEDIUM CSRF /bitwarden_license/src/Sso/Controllers/AccountController.cs: 163
MEDIUM CSRF /bitwarden_license/src/Sso/Controllers/AccountController.cs: 96
MEDIUM CSRF /bitwarden_license/src/Scim/Controllers/v2/UsersController.cs: 50
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/GroupsController.cs: 161
MEDIUM CSRF /src/Api/Auth/Controllers/EmergencyAccessController.cs: 159
MEDIUM CSRF /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs: 98
MEDIUM CSRF /bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs: 88
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 287
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 570
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 407
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 432
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 144
MEDIUM CSRF /src/Admin/AdminConsole/Controllers/OrganizationsController.cs: 308
MEDIUM CSRF /src/Admin/AdminConsole/Controllers/ProvidersController.cs: 243
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 81
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 118
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 187
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/OrganizationController.cs: 42
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/OrganizationController.cs: 42
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 323
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 722
MEDIUM CSRF /src/Api/Public/Controllers/CollectionsController.cs: 64
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/MembersController.cs: 187
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 159
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 867
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 193
MEDIUM CSRF /src/Api/AdminConsole/Controllers/ProviderUsersController.cs: 175
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 277
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 361
MEDIUM CSRF /src/Api/Tools/Controllers/ImportCiphersController.cs: 50
MEDIUM CSRF /src/Api/Tools/Controllers/ImportCiphersController.cs: 66
MEDIUM CSRF /src/Identity/Controllers/AccountsController.cs: 72
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 111
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 125
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 786
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 246
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 411
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 962
MEDIUM CSRF /src/Identity/Controllers/AccountsController.cs: 50
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 375
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1100
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1066
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1066
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 303
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 811
MEDIUM CSRF /src/Api/AdminConsole/Controllers/ProviderUsersController.cs: 188
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 627
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 627
MEDIUM CSRF /src/Api/AdminConsole/Controllers/GroupsController.cs: 260
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 174
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 572
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 193
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1043
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1043
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 774
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 246
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 411
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 375
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1017
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1017
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 222
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 286
MEDIUM CSRF /src/Api/Controllers/SettingsController.cs: 36
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 898
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 825
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 303
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 283
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 222
MEDIUM CSRF /src/Api/Auth/Controllers/TwoFactorController.cs: 403
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 926
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 117
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 283
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 86
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 218
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 583
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 300
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 318
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 583
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/GroupsController.cs: 133
MEDIUM CSRF /src/Api/AdminConsole/Controllers/ProviderOrganizationsController.cs: 53
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 530
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 449
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 545
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 283
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 283
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationsController.cs: 283
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 570
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1120
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/MembersController.cs: 150
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/MembersController.cs: 150
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 748
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 931
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 312
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/MembersController.cs: 59
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/MembersController.cs: 127
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 519
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 301
MEDIUM CSRF /src/Api/AdminConsole/Controllers/OrganizationUsersController.cs: 286
MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 221
MEDIUM CSRF /src/Api/AdminConsole/Public/Controllers/OrganizationController.cs: 42
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 156
MEDIUM CSRF /src/Api/Controllers/CollectionsController.cs: 196
MEDIUM CSRF /src/Admin/AdminConsole/Controllers/ProviderOrganizationsController.cs: 40
MEDIUM CSRF /src/Api/Auth/Controllers/WebAuthnController.cs: 101
MEDIUM CSRF /src/Api/Auth/Controllers/WebAuthnController.cs: 130
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 679
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1120
MEDIUM

More results are available on AST platform

Copy link
Member

@shane-melton shane-melton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked a bit about this solution during the FC dev sync and we came up with a potentially cleaner solution that avoids the extra repository call and adding the Unavailable property to every cipher details response.

We can create an OptionalCipherDetailsResponseModel that has a nested response model and the unavailable flag. We can then use that response type instead of the CipherDetailsResponseModel for the endpoint return type.

public class OptionalCipherDetailsResponseModel : ResponseModel
{
    public bool Unavailable { get; set; }
    
    public CipherDetailsResponseModel? Cipher { get; set; }
    
    private OptionalCipherDetailsResponseModel()
        : base("optionalCipherDetails") { }
}

Also, I do believe we'll need to duplicate this endpoint with a vNext version to maintain compatibility with other clients that use this same endpoint and will not be expecting the new model until they're updated.

Let me know what you think @Jingo88!

@Jingo88 Jingo88 requested a review from shane-melton May 17, 2024 16:12
Copy link
Member

@shane-melton shane-melton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Just a couple of test suggestions

@@ -102,6 +102,7 @@ public CipherResponseModel(CipherDetails cipher, IGlobalSettings globalSettings,
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool ViewPassword { get; set; }
public bool Unavailable { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove this property since it was moved to the OptionalCipherDetailsResponseModel

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@@ -50,6 +54,76 @@ public async Task PutPartialShouldReturnCipherWithGivenFolderAndFavoriteValues(G
Assert.Equal(isFavorite, result.Favorite);
}

[Theory, BitAutoData]
public async Task PutCollections_vNextShouldThrowException(Guid id, CipherCollectionsRequestModel model, Guid userId,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: We should put why vNext will throw an exception in the test name.

}

[Theory, BitAutoData]
public async Task PutCollections_vNextShouldSaveUpdatedCipher(Guid id, CipherCollectionsRequestModel model, Guid userId, SutProvider<CiphersController> sutProvider)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: You might be able to add a CipherDetails object to the method arguments and it'll be populated by our test Fixtures (the [BitAutoData]). Then you could remove the CreateCipherDetailsMock method.

public async Task PutCollections_vNextShouldSaveUpdatedCipher(Guid id, CipherCollectionsRequestModel model, Guid userId, CipherDetails cipherDetails, SutProvider<CiphersController> sutProvider)

{
SetupUserAndOrgMocks(id, userId, sutProvider);
var cipherDetails = CreateCipherDetailsMock(id, userId);
sutProvider.GetDependency<ICipherRepository>().GetByIdAsync(id, userId, true).ReturnsForAnyArgs(cipherDetails);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: We can mock this method to return two different values each time its called by doing .ReturnsForAnyArgs(cipherDetails, null). And that would simulate a user removing their Manage access and then we could properly test that Unassigned is set to true and the method does not throw an exception. (We might want a separate test for that path)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are great, thanks for adding!

@Jingo88 Jingo88 requested a review from shane-melton May 17, 2024 20:30
@Jingo88 Jingo88 removed the needs-qa label May 21, 2024
@Jingo88 Jingo88 merged commit 87865e8 into main May 21, 2024
49 of 50 checks passed
@Jingo88 Jingo88 deleted the AC-2447-last-can-manage-remove branch May 21, 2024 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants