From e7062ecbbb597ceed03360e484de195bcf2a0cd4 Mon Sep 17 00:00:00 2001 From: Actual Operator Date: Fri, 3 Jul 2026 15:36:33 +0000 Subject: [PATCH] Sync context files with ADRs - Update .actual/rules/cross-cutting-boundaries-coordinate-multiple-7266.md (claude) - Update .actual/rules/cross-cutting-restful-http-verbs-5544.md (claude) - Update .actual/rules/cross-cutting-controllers-log-operation-b1e7.md (claude) - Update .actual/rules/cross-cutting-controllers-handle-aggregate-730e.md (claude) - Update .actual/rules/cross-cutting-http-endpoint-methods-6d08.md (claude) - Update .actual/rules/cross-cutting-data-access-operations-44b0.md (claude) - Update .actual/rules/cross-cutting-service-controllers-separate-385f.md (claude) - Update .actual/rules/cross-cutting-multiple-fake-key-4882.md (claude) - Update .actual/rules/cross-cutting-csbindgen-configuration-specify-8c53.md (claude) - Update .actual/rules/cross-cutting-fake-cryptographic-key-ace5.md (claude) - Update .actual/rules/cross-cutting-test-fixtures-cryptographic-562a.md (claude) - Update .actual/rules/cross-cutting-build-scripts-declare-d7c8.md (claude) - Update .actual/rules/cross-cutting-generated-bindings-specify-95a4.md (claude) - Update .actual/rules/cross-cutting-rust-sdk-modules-4738.md (claude) - Update .actual/rules/cross-cutting-additional-fake-keys-c692.md (claude) - Update .actual/rules/cross-cutting-ffi-exposed-cryptographic-b670.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-keys-15e4.md (claude) - Update .actual/rules/cross-cutting-test-suites-requiring-a086.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-keys-3f21.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-keys-af1e.md (claude) - Update .actual/rules/cross-cutting-test-code-exercising-1293.md (claude) - Update .actual/rules/cross-cutting-services-implement-custom-e177.md (claude) - Update .actual/rules/cross-cutting-external-service-clients-a488.md (claude) - Update .actual/rules/cross-cutting-http-client-configurations-b862.md (claude) - Update .actual/rules/cross-cutting-cross-language-ffi-ab20.md (claude) - Update .actual/rules/cross-cutting-http-clients-registered-2dbc.md (claude) - Update .actual/rules/cross-cutting-outbound-http-communication-4af2.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-return-d4fe.md (claude) - Update .actual/rules/cross-cutting-base64-encoding-decoding-0aee.md (claude) - Update .actual/rules/cross-cutting-ffi-string-validation-6a74.md (claude) - Update .actual/rules/cross-cutting-cstr-conversions-performed-7c7f.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-returning-daae.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-accepting-2b77.md (claude) - Update .actual/rules/cross-cutting-test-code-define-c095.md (claude) - Update .actual/rules/cross-cutting-each-fake-rsa-9e21.md (claude) - Update .actual/rules/cross-cutting-modules-containing-fake-c0ec.md (claude) - Update .actual/rules/cross-cutting-production-code-paths-c368.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-key-2471.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-key-bfc4.md (claude) - Update .actual/rules/cross-cutting-hardcoded-rsa-private-4685.md (claude) - Update .actual/rules/cross-cutting-test-fixtures-use-2eaa.md (claude) - Update .actual/rules/cross-cutting-ffi-modules-document-9333.md (claude) - Update .actual/rules/cross-cutting-ffi-boundary-validation-f057.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-returning-07be.md (claude) - Update .actual/rules/cross-cutting-cstr-string-conversions-205a.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-validate-87be.md (claude) - Update .actual/rules/cross-cutting-public-ffi-functions-fbef.md (claude) - Update .actual/rules/cross-cutting-implementations-use-resource-551e.md (claude) - Update .actual/rules/cross-cutting-ffi-modules-use-f2ec.md (claude) - Update .actual/rules/cross-cutting-test-suites-include-f3f0.md (claude) - Update .actual/rules/cross-cutting-ffi-boundary-validation-d076.md (claude) - Update .actual/rules/cross-cutting-cryptographic-key-material-893a.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-use-4489.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-accepting-0ca0.md (claude) - Update .actual/rules/cross-cutting-test-code-use-30b7.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-key-cbea.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-key-fffb.md (claude) - Update .actual/rules/cross-cutting-test-fixtures-requiring-be91.md (claude) - Update .actual/rules/cross-cutting-each-fake-rsa-889f.md (claude) - Update .actual/rules/cross-cutting-fake-rsa-key-229c.md (claude) - Update .actual/rules/cross-cutting-test-code-requiring-7fee.md (claude) - Update .actual/rules/cross-cutting-context-classes-include-80d4.md (claude) - Update .actual/rules/cross-cutting-cross-language-data-2955.md (claude) - Update .actual/rules/cross-cutting-dbset-properties-organized-86b1.md (claude) - Update .actual/rules/cross-cutting-entity-types-requiring-8ef3.md (claude) - Update .actual/rules/cross-cutting-dbset-property-names-613d.md (claude) - Update .actual/rules/cross-cutting-entity-framework-dbcontext-abc6.md (claude) - Update .actual/rules/cross-cutting-additional-cryptographic-key-c744.md (claude) - Update .actual/rules/cross-cutting-ffi-boundary-functions-918a.md (claude) - Update .actual/rules/cross-cutting-cryptographic-components-cipher-bbc8.md (claude) - Update .actual/rules/cross-cutting-rsa-key-operations-065c.md (claude) - Update .actual/rules/cross-cutting-cryptographic-operations-involving-e4ca.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-that-ed1f.md (claude) - Update .actual/rules/cross-cutting-cryptographic-key-generation-b56a.md (claude) - Update .actual/rules/cross-cutting-key-management-modules-aaf3.md (claude) - Update .actual/rules/cross-cutting-shared-cryptographic-resources-16aa.md (claude) - Update .actual/rules/cross-cutting-cryptographic-operations-cipher-f6f6.md (claude) - Update .actual/rules/cross-cutting-ffi-entry-points-dcb8.md (claude) - Update .actual/rules/cross-cutting-key-generation-functions-aca2.md (claude) - Update .actual/rules/cross-cutting-cryptographic-key-types-93ca.md (claude) - Update .actual/rules/cross-cutting-ffi-modules-use-10d2.md (claude) - Update .actual/rules/cross-cutting-cryptographic-types-cipher-8303.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-use-1f6f.md (claude) - Update .actual/rules/cross-cutting-cryptographic-key-generation-fbc0.md (claude) - Update .actual/rules/cross-cutting-dedicated-free-string-5122.md (claude) - Update .actual/rules/cross-cutting-public-ffi-functions-4d31.md (claude) - Update .actual/rules/cross-cutting-string-data-crossing-3353.md (claude) - Update .actual/rules/cross-cutting-ffi-modules-use-71f1.md (claude) - Update .actual/rules/cross-cutting-public-ffi-functions-d7cf.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-return-7a63.md (claude) - Update .actual/rules/cross-cutting-input-validation-ffi-32ec.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-returning-b569.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-accepting-aff1.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-use-846b.md (claude) - Update .actual/rules/cross-cutting-memory-allocated-ffi-6520.md (claude) - Update .actual/rules/cross-cutting-ffi-string-validation-d47f.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-not-5d4a.md (claude) - Update .actual/rules/cross-cutting-string-validation-failures-12ca.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-returning-f766.md (claude) - Update .actual/rules/cross-cutting-ffi-functions-accepting-bf2a.md (claude) - Update .actual/rules/cross-cutting-test-helpers-report-03d0.md (claude) - Update .actual/rules/cross-cutting-swagger-openapi-document-b183.md (claude) - Update .actual/rules/cross-cutting-authorization-verification-tests-2daa.md (claude) - Update .actual/rules/cross-cutting-unit-tests-use-bee1.md (claude) - Update .actual/rules/cross-cutting-http-action-methods-a5bd.md (claude) - Update .actual/rules/cross-cutting-controllers-have-class-100f.md (claude) - Update .actual/rules/cross-cutting-tests-use-asserthelper-e296.md (claude) - Update .actual/rules/cross-cutting-integration-tests-use-d5ac.md (claude) - Update .actual/rules/cross-cutting-tests-validating-successful-1a26.md (claude) - Update .actual/rules/cross-cutting-authentication-failure-tests-625a.md (claude) - Update .actual/rules/cross-cutting-tests-assert-jsonvaluekind-54d7.md (claude) - Update .actual/rules/cross-cutting-integration-tests-connect-758d.md (claude) - Update .actual/rules/cross-cutting-tests-verify-number-61b8.md (claude) - Update .actual/rules/cross-cutting-logger-verification-use-910f.md (claude) - Update .actual/rules/cross-cutting-tests-verify-specific-0346.md (claude) - Update .actual/rules/cross-cutting-logger-verification-use-7680.md (claude) - Update .actual/rules/cross-cutting-unit-tests-verify-d040.md (claude) - Update .actual/rules/cross-cutting-result-types-expose-4249.md (claude) - Update .actual/rules/cross-cutting-custom-result-wrappers-23bd.md (claude) - Update .actual/rules/cross-cutting-integration-tests-use-ef0e.md (claude) - Update .actual/rules/cross-cutting-result-types-implement-459e.md (claude) - Update .actual/rules/cross-cutting-custom-result-types-8332.md (claude) - Update .actual/rules/cross-cutting-http-response-types-74bf.md (claude) - Update .actual/rules/cross-cutting-services-extend-base-95a6.md (claude) - Update .actual/rules/cross-cutting-cache-configuration-integrate-4625.md (claude) - Update .actual/rules/cross-cutting-cache-service-registration-2dcf.md (claude) - Update .actual/rules/cross-cutting-cache-configuration-use-f590.md (claude) - Update .actual/rules/cross-cutting-redis-connection-failures-4ea5.md (claude) - Update .actual/rules/cross-cutting-cache-service-registration-175e.md (claude) - Update .actual/rules/cross-cutting-additional-diagnostic-context-304d.md (claude) - Update .actual/rules/cross-cutting-logging-statements-use-3a5d.md (claude) - Update .actual/rules/cross-cutting-cache-service-registration-46f7.md (claude) - Update .actual/rules/cross-cutting-error-log-entries-5cd6.md (claude) - Update .actual/rules/cross-cutting-redis-connection-failures-7cfd.md (claude) - Update .actual/rules/cross-cutting-cache-implementations-expose-f10e.md (claude) - Update .actual/rules/cross-cutting-cache-service-registration-1246.md (claude) - Update .actual/rules/cross-cutting-cache-configuration-use-49c3.md (claude) - Update .actual/rules/cross-cutting-redis-connection-failures-ffdd.md (claude) - Update .actual/rules/cross-cutting-cache-service-registration-b5a1.md (claude) - Update .actual/rules/cross-cutting-distributed-cache-implementations-7a7e.md (claude) - Update .actual/rules/cross-cutting-extended-cache-utilities-aaaf.md (claude) - Update .actual/rules/cross-cutting-cache-implementations-use-92c0.md (claude) - Update .actual/rules/cross-cutting-cache-registration-encapsulated-b774.md (claude) - Update .actual/rules/cross-cutting-redis-connection-failures-6ee5.md (claude) - Update .actual/rules/cross-cutting-redis-connections-established-6e7b.md (claude) - Update .actual/rules/cross-cutting-distributed-caching-implementations-859c.md (claude) - Update .actual/rules/cross-cutting-implementation-suppress-specific-c43d.md (claude) - Update .actual/rules/cross-cutting-services-processing-notifications-c775.md (claude) - Update .actual/rules/cross-cutting-logging-statements-validation-0931.md (claude) - Update .actual/rules/cross-cutting-push-notification-services-2769.md (claude) - Update .actual/rules/cross-cutting-push-notification-services-09af.md (claude) - Update .actual/rules/cross-cutting-controllers-bit-billing-446f.md (claude) - Update .actual/rules/cross-cutting-billing-endpoints-that-b5d9.md (claude) - Update .actual/rules/cross-cutting-authorization-requirements-billing-3f88.md (claude) - Update .actual/rules/cross-cutting-organization-parameters-billing-b978.md (claude) - Update .actual/rules/cross-cutting-organization-billing-controller-da79.md (claude) - Update .actual/rules/cross-cutting-organization-billing-endpoints-1404.md (claude) - Update .actual/rules/cross-cutting-controllers-log-successful-0929.md (claude) - Update .actual/rules/cross-cutting-log-entries-not-bf81.md (claude) - Update .actual/rules/cross-cutting-controllers-handling-external-8ed8.md (claude) - Update .actual/rules/cross-cutting-log-messages-describe-db43.md (claude) - Update .actual/rules/cross-cutting-exception-logging-within-5e08.md (claude) - Update .actual/rules/cross-cutting-log-entries-failures-fb74.md (claude) - Update .actual/rules/cross-cutting-controllers-authorize-attributes-3853.md (claude) - Update .actual/rules/cross-cutting-return-fallback-responses-ecab.md (claude) - Update .actual/rules/cross-cutting-use-logerror-level-2e07.md (claude) - Update .actual/rules/cross-cutting-log-messages-describe-7507.md (claude) - Update .actual/rules/cross-cutting-wrap-external-service-ce6b.md (claude) - Update .actual/rules/cross-cutting-include-structured-contextual-052d.md (claude) - Update .actual/rules/cross-cutting-log-exceptions-external-4360.md (claude) - Update .actual/rules/cross-cutting-authorization-requirement-classes-2368.md (claude) - Update .actual/rules/cross-cutting-authorization-logic-not-ca94.md (claude) - Update .actual/rules/cross-cutting-public-endpoints-that-46c1.md (claude) - Update .actual/rules/cross-cutting-controllers-use-authorize-1b71.md (claude) - Update .actual/rules/cross-cutting-authorization-attributes-placed-d871.md (claude) - Update .actual/rules/cross-cutting-custom-authorization-requirements-789a.md (claude) - Update .actual/rules/cross-cutting-controller-actions-that-753e.md (claude) - Update .actual/rules/cross-cutting-controllers-combine-multiple-8f6f.md (claude) - Update .actual/rules/cross-cutting-controllers-use-allowanonymous-2156.md (claude) - Update .actual/rules/cross-cutting-custom-authorization-requirements-7482.md (claude) - Update .actual/rules/cross-cutting-controller-action-methods-3351.md (claude) - Update .actual/rules/cross-cutting-authorization-attributes-applied-9899.md (claude) - Update .actual/rules/cross-cutting-controller-action-methods-981f.md (claude) - Update .actual/rules/cross-cutting-controllers-combine-multiple-46a6.md (claude) - Update .actual/rules/cross-cutting-public-endpoints-that-dff2.md (claude) - Update .actual/rules/cross-cutting-authorization-failures-throw-7ee9.md (claude) - Update .actual/rules/cross-cutting-controllers-use-icurrentcontext-7929.md (claude) - Update .actual/rules/cross-cutting-controllers-apply-authorization-155e.md (claude) - Update .actual/rules/cross-cutting-authorization-requirement-classes-e999.md (claude) - Update .actual/rules/cross-cutting-protected-controller-actions-358e.md (claude) - Update .actual/rules/cross-cutting-additional-authorization-checks-1f05.md (claude) - Update .actual/rules/cross-cutting-endpoints-that-allow-4471.md (claude) - Update .actual/rules/cross-cutting-authorization-requirements-named-db81.md (claude) - Update .actual/rules/cross-cutting-controllers-use-base-de8d.md (claude) - Update .actual/rules/cross-cutting-typed-requirement-classes-b695.md (claude) - Update .actual/rules/cross-cutting-authorization-attributes-placed-9af6.md (claude) - Update .actual/rules/cross-cutting-adminconsole-controller-endpoints-9b4c.md (claude) - Update .actual/rules/cross-cutting-public-endpoints-that-05a5.md (claude) - Update .actual/rules/cross-cutting-controllers-managing-related-25e3.md (claude) - Update .actual/rules/cross-cutting-authorization-attributes-use-9921.md (claude) - Update .actual/rules/cross-cutting-controller-actions-not-1aa2.md (claude) - Update .actual/rules/cross-cutting-authorization-requirements-declared-3c80.md (claude) - Update .actual/rules/cross-cutting-internal-controller-actions-e0ea.md (claude) - Update .actual/rules/cross-cutting-controllers-use-multiple-79e8.md (claude) - Update .actual/rules/cross-cutting-authorization-checks-occur-6a87.md (claude) - Update .actual/rules/cross-cutting-controllers-separate-read-1915.md (claude) - Update .actual/rules/cross-cutting-self-modification-operations-9860.md (claude) - Update .actual/rules/cross-cutting-controllers-apply-custom-0144.md (claude) - Update .actual/rules/cross-cutting-authorization-failures-authorizeasync-a3f2.md (claude) - Update .actual/rules/cross-cutting-endpoints-modifying-collection-9595.md (claude) - Update .actual/rules/cross-cutting-controllers-bit-adminconsole-60f4.md (claude) - Update .actual/rules/cross-cutting-read-only-collection-e4b3.md (claude) - Update .actual/rules/cross-cutting-self-modification-operations-b5aa.md (claude) - Update .actual/rules/cross-cutting-authorization-requirements-enforced-e334.md (claude) - Update .actual/rules/cross-cutting-controllers-use-iauthorizationservice-e782.md (claude) - Update .actual/rules/cross-cutting-collection-access-modifications-3ddb.md (claude) - Update .actual/rules/cross-cutting-failed-authorization-checks-d17b.md (claude) - Update .actual/rules/cross-cutting-authorization-checks-execute-2769.md (claude) - Update .actual/rules/cross-cutting-services-register-multiple-1cc0.md (claude) - Update .actual/rules/cross-cutting-http-request-headers-a358.md (claude) - Update .actual/rules/cross-cutting-external-client-calls-7e79.md (claude) - Update .actual/rules/cross-cutting-test-environments-use-bc29.md (claude) - Update .actual/rules/cross-cutting-http-clients-that-7859.md (claude) - Update .actual/rules/cross-cutting-named-http-clients-5dbb.md (claude) - Update .actual/rules/cross-cutting-external-http-client-d376.md (claude) - Update .actual/rules/cross-cutting-test-environments-use-9167.md (claude) - Update .actual/rules/cross-cutting-bulk-operations-verify-d6b9.md (claude) - Update .actual/rules/cross-cutting-custom-authorization-requirements-fcd6.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-configured-4a49.md (claude) - Update .actual/rules/cross-cutting-authorization-failures-throw-5a99.md (claude) - Update .actual/rules/cross-cutting-controllers-inject-iauthorizationservice-aa26.md (claude) - Update .actual/rules/cross-cutting-authorization-checks-performed-781f.md (claude) - Update .actual/rules/cross-cutting-protected-controller-actions-2188.md (claude) - Update .actual/rules/cross-cutting-controllers-combine-declarative-1a73.md (claude) - Update .actual/rules/cross-cutting-test-environments-configure-a1e8.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-registered-94d3.md (claude) - Update .actual/rules/cross-cutting-controllers-throw-notfoundexception-cdc8.md (claude) - Update .actual/rules/cross-cutting-authorization-checks-call-d107.md (claude) - Update .actual/rules/cross-cutting-controllers-inject-iauthorizationservice-d74b.md (claude) - Update .actual/rules/cross-cutting-protected-controller-endpoints-77bc.md (claude) - Update .actual/rules/cross-cutting-exception-handling-tests-94de.md (claude) - Update .actual/rules/cross-cutting-tests-use-async-e659.md (claude) - Update .actual/rules/cross-cutting-tests-cover-both-d730.md (claude) - Update .actual/rules/cross-cutting-tests-verify-that-de1c.md (claude) - Update .actual/rules/cross-cutting-tests-validate-operation-8bf3.md (claude) - Update .actual/rules/cross-cutting-tests-verify-query-eeeb.md (claude) - Update .actual/rules/cross-cutting-tests-use-dependency-eab0.md (claude) - Update .actual/rules/cross-cutting-unit-tests-query-8f98.md (claude) - Update .actual/rules/cross-cutting-tests-use-linq-ad5d.md (claude) - Update .actual/rules/cross-cutting-test-fixture-setup-79b4.md (claude) - Update .actual/rules/cross-cutting-tests-verify-asynchronous-557f.md (claude) - Update .actual/rules/cross-cutting-tests-use-received-b50c.md (claude) - Update .actual/rules/cross-cutting-tests-verifying-exceptions-de9f.md (claude) - Update .actual/rules/cross-cutting-test-methods-that-9dfa.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-combine-b65c.md (claude) - Update .actual/rules/cross-cutting-authorization-middleware-added-f25d.md (claude) - Update .actual/rules/cross-cutting-test-environments-define-bd63.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-named-4edb.md (claude) - Update .actual/rules/cross-cutting-scim-endpoint-authorization-f6bd.md (claude) - Update .actual/rules/cross-cutting-production-authorization-policies-a09e.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-registered-b7a3.md (claude) - Update .actual/rules/cross-cutting-integration-test-factories-1764.md (claude) - Update .actual/rules/cross-cutting-test-authentication-schemes-58ef.md (claude) - Update .actual/rules/cross-cutting-authentication-middleware-registered-f260.md (claude) - Update .actual/rules/cross-cutting-test-authentication-handlers-d009.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-require-0cb9.md (claude) - Update .actual/rules/cross-cutting-authentication-handlers-inherit-76ba.md (claude) - Update .actual/rules/cross-cutting-scim-service-endpoints-f9a4.md (claude) - Update .actual/rules/cross-cutting-authentication-scheme-configuration-171a.md (claude) - Update .actual/rules/cross-cutting-named-authorization-policies-14d3.md (claude) - Update .actual/rules/cross-cutting-authorization-configuration-applied-925c.md (claude) - Update .actual/rules/cross-cutting-test-environments-use-f608.md (claude) - Update .actual/rules/cross-cutting-scope-based-authorization-bd9c.md (claude) - Update .actual/rules/cross-cutting-production-authorization-policies-0d1f.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-configured-dbd8.md (claude) - Update .actual/rules/cross-cutting-domain-business-logic-5463.md (claude) - Update .actual/rules/cross-cutting-authentication-schemes-configured-ef9d.md (claude) - Update .actual/rules/cross-cutting-test-environments-use-f094.md (claude) - Update .actual/rules/cross-cutting-authorization-middleware-added-7b79.md (claude) - Update .actual/rules/cross-cutting-production-scim-policies-3121.md (claude) - Update .actual/rules/cross-cutting-scim-named-policy-cbc1.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-registered-fcbd.md (claude) - Update .actual/rules/cross-cutting-test-authentication-configuration-f8dc.md (claude) - Update .actual/rules/cross-cutting-test-claims-include-d13f.md (claude) - Update .actual/rules/cross-cutting-test-authentication-schemes-ba44.md (claude) - Update .actual/rules/cross-cutting-test-authentication-handlers-c778.md (claude) - Update .actual/rules/cross-cutting-test-authentication-handlers-98aa.md (claude) - Update .actual/rules/cross-cutting-integration-test-projects-bc7e.md (claude) - Update .actual/rules/cross-cutting-test-factories-use-7687.md (claude) - Update .actual/rules/cross-cutting-http-requests-scim-d271.md (claude) - Update .actual/rules/cross-cutting-test-authentication-handlers-9daa.md (claude) - Update .actual/rules/cross-cutting-data-access-operations-1aca.md (claude) - Update .actual/rules/cross-cutting-json-serialization-use-2eb1.md (claude) - Update .actual/rules/cross-cutting-scim-integration-tests-c5f8.md (claude) - Update .actual/rules/cross-cutting-test-authentication-handlers-9e7c.md (claude) - Update .actual/rules/cross-cutting-authorization-policies-use-6910.md (claude) - Update .actual/rules/cross-cutting-service-registration-occur-aab5.md (claude) - Update .actual/rules/cross-cutting-authentication-schemes-registered-a829.md (claude) - Update .actual/rules/cross-cutting-test-environments-register-a385.md (claude) - Update .actual/rules/cross-cutting-infrastructure-services-registered-9d84.md (claude) - Update .actual/rules/cross-cutting-tests-append-custom-9f5d.md (claude) - Update .actual/rules/cross-cutting-test-servers-inject-716f.md (claude) - Update .actual/rules/cross-cutting-test-authorization-policies-9816.md (claude) - Update .actual/rules/cross-cutting-scim-endpoint-tests-3944.md (claude) - Update .actual/rules/cross-cutting-test-factories-configure-fdb2.md (claude) - Update .actual/rules/cross-cutting-integration-tests-call-f5ec.md (claude) - Update CLAUDE.md (claude) - Update AGENTS.md (agents) - Update docs/adr/72668b21-de9e-48dc-a3e4-390f41bff7b5-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-boundaries-coordinate-multiple.md (docs) - Update docs/adr/5544cf8d-e169-4f44-87c2-4fbb865f009f-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-restful-http-verbs.md (docs) - Update docs/adr/b1e7db38-2432-46ef-944c-12699fc054f2-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-log-operation.md (docs) - Update docs/adr/730eeb26-7617-47a6-ac66-d0b722c94a7c-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-handle-aggregate.md (docs) - Update docs/adr/6d08223f-13b7-41cc-87df-78b85c3f2721-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-http-endpoint-methods.md (docs) - Update docs/adr/44b0e5cd-7f0f-4a32-8d94-965b081e74cf-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-data-access-operations.md (docs) - Update docs/adr/385fbeac-2009-4964-97f0-f639567e8c51-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-service-controllers-separate.md (docs) - Update docs/adr/4882b808-5c7b-4443-b150-5b4d9e5492ec-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-multiple-fake-key.md (docs) - Update docs/adr/8c53f1bd-3055-4879-a45c-7be3e98c1a96-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-csbindgen-configuration-specify.md (docs) - Update docs/adr/ace52160-226e-413e-80cd-682f2d78db99-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-fake-cryptographic-key.md (docs) - Update docs/adr/562a1fb2-8e5c-4ec8-9b46-1106e26df9fe-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-test-fixtures-cryptographic.md (docs) - Update docs/adr/d7c80df6-2821-40b1-896c-773d22cd3543-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-build-scripts-declare.md (docs) - Update docs/adr/95a40c26-775a-4a73-b44e-6fc159188177-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-generated-bindings-specify.md (docs) - Update docs/adr/4738e6e5-da0f-4f81-8170-17e1787a2708-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-rust-sdk-modules.md (docs) - Update docs/adr/c6925c30-52cd-4b6a-b3a6-106604368441-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-additional-fake-keys.md (docs) - Update docs/adr/b6700091-00ec-4e70-84f3-648c1a9bb652-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-ffi-exposed-cryptographic.md (docs) - Update docs/adr/15e40d0d-ad1f-48d7-93c8-4a2a34a133b1-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md (docs) - Update docs/adr/a0860e4d-6381-47ea-b146-63016a984641-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-suites-requiring.md (docs) - Update docs/adr/3f212963-2a7a-4edd-83a7-6faf9f37b6b4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md (docs) - Update docs/adr/af1e829e-bf47-40d9-bc3a-c282b0a91de4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md (docs) - Update docs/adr/129355f1-5bef-4966-8db2-3b85d084cd4c-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-code-exercising.md (docs) - Update docs/adr/e1776714-355e-4af4-8981-ebbc0835371b-adopt-http-client-abstraction-for-external-service-integration-services-implement-custom.md (docs) - Update docs/adr/a4882536-e976-4b5b-b9c4-76184baf709d-adopt-http-client-abstraction-for-external-service-integration-external-service-clients.md (docs) - Update docs/adr/b862eccf-5190-4192-b73e-c7cee246b8c3-adopt-http-client-abstraction-for-external-service-integration-http-client-configurations.md (docs) - Update docs/adr/ab20330d-42a3-40d9-954b-b5fb1aaeff15-adopt-http-client-abstraction-for-external-service-integration-cross-language-ffi.md (docs) - Update docs/adr/2dbcdbcc-a1f8-4732-afa0-68852b3eec23-adopt-http-client-abstraction-for-external-service-integration-http-clients-registered.md (docs) - Update docs/adr/4af296a2-06e6-4fea-abfc-0a806e7df47f-adopt-http-client-abstraction-for-external-service-integration-outbound-http-communication.md (docs) - Update docs/adr/d4fedf70-1502-4676-a146-a2f18eee1340-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-return.md (docs) - Update docs/adr/0aeea845-ad1a-44d3-a49f-f78e57388421-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-base64-encoding-decoding.md (docs) - Update docs/adr/6a74e276-66db-449a-929c-65a5f57ce685-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md (docs) - Update docs/adr/7c7fbe23-7f8f-4fdd-afdc-b01aa29eac8e-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-cstr-conversions-performed.md (docs) - Update docs/adr/daae2af9-369d-4fcc-b20a-d10c0f1d03f6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md (docs) - Update docs/adr/2b775808-03a5-4387-84e4-0cb3a0b2162a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md (docs) - Update docs/adr/c0954ece-5f93-4c49-acaf-337ccb671903-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-test-code-define.md (docs) - Update docs/adr/9e21df4f-bead-4cac-b324-68e089a7ab17-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-each-fake-rsa.md (docs) - Update docs/adr/c0eccdcc-f9f8-4371-85bc-935d747950f8-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-modules-containing-fake.md (docs) - Update docs/adr/c368c23f-80fd-4b43-8ae5-2c4f9d2cb067-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-production-code-paths.md (docs) - Update docs/adr/2471eb0e-c976-49b7-9c1b-8d163631e101-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md (docs) - Update docs/adr/bfc4a3c9-a71f-4235-8343-7602daa8576c-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md (docs) - Update docs/adr/46855cf7-686a-4e5e-9502-81b84d5cf9c5-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-hardcoded-rsa-private.md (docs) - Update docs/adr/2eaa7b00-5d0f-40bf-b471-3a0993ccac0e-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-test-fixtures-use.md (docs) - Update docs/adr/93330207-06c0-4452-9a7a-8d3d66685272-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-modules-document.md (docs) - Update docs/adr/f0570cf5-0f1d-4069-81c2-d602ba323070-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-boundary-validation.md (docs) - Update docs/adr/07bef05b-46f9-49a1-8146-08515ab97e21-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-returning.md (docs) - Update docs/adr/205a829c-f4e2-45ae-9b0a-5ccbb7494a9b-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-cstr-string-conversions.md (docs) - Update docs/adr/87be164b-bd95-43a3-ae40-6f0fa34ced4a-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-validate.md (docs) - Update docs/adr/fbefe97a-b42f-4765-86e9-e0fa40079305-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-public-ffi-functions.md (docs) - Update docs/adr/551e5ab9-76a3-4125-9ac8-ad71f0e4f1f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-implementations-use-resource.md (docs) - Update docs/adr/f2ec3be2-47e8-4626-9d21-f6a29049c4f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-modules-use.md (docs) - Update docs/adr/f3f0b5bc-743a-4b38-b3c9-7f1376973b7a-validate-ffi-input-using-rust-type-system-and-c-string-conversions-test-suites-include.md (docs) - Update docs/adr/d0768299-875b-48c7-8762-179423ce299e-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-boundary-validation.md (docs) - Update docs/adr/893a7c18-91d2-4ec7-b446-5ad2251fa57d-validate-ffi-input-using-rust-type-system-and-c-string-conversions-cryptographic-key-material.md (docs) - Update docs/adr/44897d9c-1b04-4264-9ce1-6b1a6b4094d8-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-use.md (docs) - Update docs/adr/0ca06cfe-e64d-42d3-b847-78554bc2595f-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-accepting.md (docs) - Update docs/adr/30b72ec9-4f3f-4f1c-8352-06631ef7b00f-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-use.md (docs) - Update docs/adr/cbeaee5b-97cf-4120-9994-da5d9621a7df-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md (docs) - Update docs/adr/fffb6c6b-569b-4502-bfd8-77134aa02e25-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md (docs) - Update docs/adr/be91c795-209c-4756-a476-c7299c3bd4f9-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-fixtures-requiring.md (docs) - Update docs/adr/889fa803-9d10-47fd-8fa5-96a0dd4899e7-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-each-fake-rsa.md (docs) - Update docs/adr/229cd360-3e71-4202-a291-9c178aaed87e-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md (docs) - Update docs/adr/7fee142b-06b9-432b-81ec-911cb732b053-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-requiring.md (docs) - Update docs/adr/80d4fa0c-c256-4ad8-be81-9dd26277d7de-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-context-classes-include.md (docs) - Update docs/adr/29556473-2e70-4ba2-aea9-40b4dd4a120c-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-cross-language-data.md (docs) - Update docs/adr/86b1ddae-ffa0-4f45-8f93-0ab9ec630cc8-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-properties-organized.md (docs) - Update docs/adr/8ef3fe32-3e55-45e5-9b27-56d1ca7de403-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-types-requiring.md (docs) - Update docs/adr/613d377b-9885-4202-8c35-5dc7040c6b9b-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-property-names.md (docs) - Update docs/adr/abc628f2-d591-45bf-8221-4b8a79fe0b5a-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-framework-dbcontext.md (docs) - Update docs/adr/c74440d5-44bb-41b7-9a51-afde8974ce39-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-additional-cryptographic-key.md (docs) - Update docs/adr/918af20b-0276-447f-88f2-b10ecc4f55a9-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-boundary-functions.md (docs) - Update docs/adr/bbc83d26-64c4-4e7c-a505-7a9b2665a645-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-components-cipher.md (docs) - Update docs/adr/065cedd3-19a8-40d8-a11f-e45077be274a-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-rsa-key-operations.md (docs) - Update docs/adr/e4cab412-0466-4df2-9c64-80bb2e9e897c-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-operations-involving.md (docs) - Update docs/adr/ed1f3bfd-e75f-4a51-b083-1e9ff6c63c3f-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-functions-that.md (docs) - Update docs/adr/b56acf9d-5917-4557-8014-57020819af23-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-key-generation.md (docs) - Update docs/adr/aaf34ea5-54c3-43cc-a210-03bf483dedb2-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-management-modules.md (docs) - Update docs/adr/16aa9187-10a7-4726-9b4c-ec41d1641aaa-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-shared-cryptographic-resources.md (docs) - Update docs/adr/f6f6d796-e5f5-455e-9ee0-463991270cce-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-operations-cipher.md (docs) - Update docs/adr/dcb80ee8-6360-45cd-b6b0-608633a0450d-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-ffi-entry-points.md (docs) - Update docs/adr/aca2792a-f5da-41d3-91ed-f225a11fc94c-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-generation-functions.md (docs) - Update docs/adr/93ca6910-d73c-400a-9049-65abe6c60978-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-key-types.md (docs) - Update docs/adr/10d29bf0-d5fa-475e-9947-741b253d41f4-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-modules-use.md (docs) - Update docs/adr/8303fcd7-1b32-4ea7-a6c0-a42d3079eac9-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-types-cipher.md (docs) - Update docs/adr/1f6f7f84-717f-498e-b845-592fe052e6d8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-functions-use.md (docs) - Update docs/adr/fbc0365b-bba7-4bc2-b4bb-0667cfe7b8d6-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-key-generation.md (docs) - Update docs/adr/51226e02-a611-40b7-9343-4e32cd7697ba-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-dedicated-free-string.md (docs) - Update docs/adr/4d319375-586c-4c89-974a-cf57f147755c-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-public-ffi-functions.md (docs) - Update docs/adr/335364a7-51cc-460c-94b0-ceb75ebe48f8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-string-data-crossing.md (docs) - Update docs/adr/71f1e1e1-3305-40ed-8ef5-c8334377ee96-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-modules-use.md (docs) - Update docs/adr/d7cf8560-2b44-4465-8754-102fecae7236-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-public-ffi-functions.md (docs) - Update docs/adr/7a63602c-8f91-4721-82e4-587068e3f75f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-return.md (docs) - Update docs/adr/32ec4bdf-3e54-40c5-924a-208e17fbd125-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-input-validation-ffi.md (docs) - Update docs/adr/b569cad3-d31f-4e1c-b491-858e64c8d8bf-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-returning.md (docs) - Update docs/adr/aff187d4-e8a6-49ef-9f8a-0a6f86b4d48f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-accepting.md (docs) - Update docs/adr/846bc329-4589-4607-9efd-6033c355563a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-use.md (docs) - Update docs/adr/652092c8-86ba-4e27-a202-23567b7338de-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-memory-allocated-ffi.md (docs) - Update docs/adr/d47f7772-dcb8-4c92-a949-c0a8fef043ad-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md (docs) - Update docs/adr/5d4a8535-38ea-4839-8a6d-38029726ae65-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-not.md (docs) - Update docs/adr/12ca8d34-55df-4dd0-accb-6f82613bb8d6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-string-validation-failures.md (docs) - Update docs/adr/f766c552-4097-49a8-ab9c-efc885073a79-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md (docs) - Update docs/adr/bf2ab4ec-7f8d-492a-b356-25c2f0b9eac4-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md (docs) - Update docs/adr/03d051fd-23a0-4eb5-b917-18767dc87480-enforce-authorization-attributes-on-api-controllers-via-unit-tests-test-helpers-report.md (docs) - Update docs/adr/b18395c7-d0da-4b8c-8091-bb4e2da35352-enforce-authorization-attributes-on-api-controllers-via-unit-tests-swagger-openapi-document.md (docs) - Update docs/adr/2daa6496-ac17-4ea7-a429-ab8b08960dc9-enforce-authorization-attributes-on-api-controllers-via-unit-tests-authorization-verification-tests.md (docs) - Update docs/adr/bee1ce59-2afa-4c78-a877-66249177f453-enforce-authorization-attributes-on-api-controllers-via-unit-tests-unit-tests-use.md (docs) - Update docs/adr/a5bdfb20-cb01-4912-b128-8694d29c60b6-enforce-authorization-attributes-on-api-controllers-via-unit-tests-http-action-methods.md (docs) - Update docs/adr/100f3767-af9d-45f5-885f-9a4456ace179-enforce-authorization-attributes-on-api-controllers-via-unit-tests-controllers-have-class.md (docs) - Update docs/adr/e296cb7f-ba9f-4ae7-9961-70276b3c544a-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-use-asserthelper.md (docs) - Update docs/adr/d5ace3d3-7f05-4d88-bfe2-cc82cf13a7e3-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-use.md (docs) - Update docs/adr/1a263ad8-362a-4bed-8d4c-ff152c9ea4f0-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-validating-successful.md (docs) - Update docs/adr/625af6eb-2999-45fa-865d-97ab13837d42-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-authentication-failure-tests.md (docs) - Update docs/adr/54d7258e-000f-4f7d-8079-9c820d805cdd-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-assert-jsonvaluekind.md (docs) - Update docs/adr/758dcc20-8b27-421a-a3a3-d27e3e2f5d57-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-connect.md (docs) - Update docs/adr/61b87c11-8189-45b9-bdb0-07a0b193e382-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-number.md (docs) - Update docs/adr/910fe798-7802-4a1e-9329-07007b1ea997-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md (docs) - Update docs/adr/03460212-4b7e-492f-8a14-fa879008634d-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-specific.md (docs) - Update docs/adr/76807d1e-075a-4dfb-8034-4d3ce093ebe1-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md (docs) - Update docs/adr/d0407e8f-b352-48a5-b1a6-53fdb423ddc1-verify-logger-invocations-in-unit-tests-for-observability-components-unit-tests-verify.md (docs) - Update docs/adr/4249ecc3-367a-40f2-99f8-b23616365041-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-expose.md (docs) - Update docs/adr/23bdf879-b4fe-4d4a-bdde-45ddc7890b0b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-wrappers.md (docs) - Update docs/adr/ef0e6a8b-31a8-4d14-8127-dda7d12de886-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-integration-tests-use.md (docs) - Update docs/adr/459ea228-d332-4b52-a7a4-490be0ffde40-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-implement.md (docs) - Update docs/adr/8332d4f6-d878-4891-85f3-f261cf790c5f-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-types.md (docs) - Update docs/adr/74bf715a-53ae-4c13-be5f-a29c89c0478b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-http-response-types.md (docs) - Update docs/adr/95a61a86-bb62-4b1a-8d77-320971142c14-expose-extended-cache-configuration-as-public-api-contract-services-extend-base.md (docs) - Update docs/adr/46259ca9-c088-47b1-b31a-417242ff61a0-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-integrate.md (docs) - Update docs/adr/2dcfc033-1bdc-4e09-9c4f-fd7199b9e904-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md (docs) - Update docs/adr/f59075ec-7f34-4421-9572-193d3c9ee869-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-use.md (docs) - Update docs/adr/4ea57ab2-43b0-4e07-8de2-6d07829a71c8-expose-extended-cache-configuration-as-public-api-contract-redis-connection-failures.md (docs) - Update docs/adr/175e5898-be14-42bf-af34-1bbf3b90ece2-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md (docs) - Update docs/adr/304d2cd5-6451-4c86-a8c1-c6eca4bbcdc7-log-redis-connection-failures-in-distributed-cache-extensions-additional-diagnostic-context.md (docs) - Update docs/adr/3a5da651-71a4-4609-ac03-ac704880f5b9-log-redis-connection-failures-in-distributed-cache-extensions-logging-statements-use.md (docs) - Update docs/adr/46f70fba-6b32-4984-a7f2-97fc8f124e81-log-redis-connection-failures-in-distributed-cache-extensions-cache-service-registration.md (docs) - Update docs/adr/5cd6ec70-a27a-44ff-a08f-ccf37d7b0e93-log-redis-connection-failures-in-distributed-cache-extensions-error-log-entries.md (docs) - Update docs/adr/7cfd3bd7-4395-4876-b379-f8b4e676c501-log-redis-connection-failures-in-distributed-cache-extensions-redis-connection-failures.md (docs) - Update docs/adr/f10e50f9-1793-4078-bf2c-f87b82a11333-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-implementations-expose.md (docs) - Update docs/adr/1246ffac-4184-4102-bae0-11c0852aef3d-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md (docs) - Update docs/adr/49c3eb8d-cc66-4014-b066-2f29f3d823ee-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-configuration-use.md (docs) - Update docs/adr/ffddbcb9-7c00-4a51-a626-c52702ef8e99-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-redis-connection-failures.md (docs) - Update docs/adr/b5a143c2-0481-4e32-8cb8-cfafca5ce423-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md (docs) - Update docs/adr/7a7eb6e8-901b-416d-980b-f0a6b1158259-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-distributed-cache-implementations.md (docs) - Update docs/adr/aaaf4b07-0f57-4370-94a8-edfd8a440f2c-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-extended-cache-utilities.md (docs) - Update docs/adr/92c03b28-7ea3-46c3-aa8f-b89cb67bcb9b-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-implementations-use.md (docs) - Update docs/adr/b774d498-b072-4740-8391-71e62deb6dd4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-registration-encapsulated.md (docs) - Update docs/adr/6ee5e5c9-4eba-4aa1-a0c7-c45396eddc9f-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connection-failures.md (docs) - Update docs/adr/6e7b7016-eb84-47d3-8a29-a78cd5f8e5b4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connections-established.md (docs) - Update docs/adr/859c13ba-4abb-4b8d-85ce-aac9e8f13ed5-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-distributed-caching-implementations.md (docs) - Update docs/adr/c43d4ce1-3b5f-4e6d-8f9b-8a57664a6f36-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-implementation-suppress-specific.md (docs) - Update docs/adr/c775e1b6-3ca1-4da9-88d0-761fad4b473e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-services-processing-notifications.md (docs) - Update docs/adr/0931104c-fe38-4781-b9f7-a75a7a4e7450-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-logging-statements-validation.md (docs) - Update docs/adr/27694fe9-9e4c-49dc-9467-1a147b3a864e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md (docs) - Update docs/adr/09afc0f6-e646-46ab-b05d-69adb04ccfd7-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md (docs) - Update docs/adr/446f3d19-4bdb-4bd7-aa9f-d1e9a2c73445-enforce-organization-scoped-authorization-requirements-for-billing-operations-controllers-bit-billing.md (docs) - Update docs/adr/b5d99c3b-d0d8-4d81-bcde-af3fcc76ee3f-enforce-organization-scoped-authorization-requirements-for-billing-operations-billing-endpoints-that.md (docs) - Update docs/adr/3f888895-b046-4f11-bc2d-3b22882e76b0-enforce-organization-scoped-authorization-requirements-for-billing-operations-authorization-requirements-billing.md (docs) - Update docs/adr/b97877a2-3da0-42cb-812b-54c702b80a92-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-parameters-billing.md (docs) - Update docs/adr/da790b60-15b3-4bf4-9937-0fe3f9aadba9-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-controller.md (docs) - Update docs/adr/1404fbba-3345-4129-a549-1e89fd72a4fa-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-endpoints.md (docs) - Update docs/adr/0929cc83-dbde-4cc8-823b-acab2af6ef9e-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-log-successful.md (docs) - Update docs/adr/bf81a88a-0c42-4cb9-b420-079805d48869-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-not.md (docs) - Update docs/adr/8ed82d97-4d70-4553-988f-f79331b9ef22-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-handling-external.md (docs) - Update docs/adr/db430582-fad9-41d5-92df-f2d3f63b417b-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-messages-describe.md (docs) - Update docs/adr/5e080c9b-be10-4cf4-aa70-fe5e5d4cf4a3-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-exception-logging-within.md (docs) - Update docs/adr/fb740243-8248-4287-971c-36a708d8c36a-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-failures.md (docs) - Update docs/adr/38530c47-f864-481a-9c77-d612e8841263-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-authorize-attributes.md (docs) - Update docs/adr/ecab59e9-ab15-4328-a38c-6ebe589b784d-use-structured-logging-with-contextual-parameters-for-external-service-failures-return-fallback-responses.md (docs) - Update docs/adr/2e078989-f0a0-4944-b666-6028a7c74890-use-structured-logging-with-contextual-parameters-for-external-service-failures-use-logerror-level.md (docs) - Update docs/adr/7507ed7f-d610-4f43-853a-2f85cc6254d9-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-messages-describe.md (docs) - Update docs/adr/ce6b97e8-0b9b-45b4-bc6f-c2adb5a24a9c-use-structured-logging-with-contextual-parameters-for-external-service-failures-wrap-external-service.md (docs) - Update docs/adr/052d6875-cc91-4f25-b7be-7a8e5370916f-use-structured-logging-with-contextual-parameters-for-external-service-failures-include-structured-contextual.md (docs) - Update docs/adr/4360e829-692d-4f6c-9197-2e9deaa4506e-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-exceptions-external.md (docs) - Update docs/adr/2368cf82-a8ac-4c40-a698-2eb3e6e5c486-adopt-attribute-based-authorization-model-for-controller-actions-authorization-requirement-classes.md (docs) - Update docs/adr/ca94f258-8ca7-4c19-aad5-3ba8b6328c0f-adopt-attribute-based-authorization-model-for-controller-actions-authorization-logic-not.md (docs) - Update docs/adr/46c10ab6-e5e1-43e2-9c32-a4ae1256f5db-adopt-attribute-based-authorization-model-for-controller-actions-public-endpoints-that.md (docs) - Update docs/adr/1b71f2d5-afd2-4ba4-8a75-16c87a1823dc-adopt-attribute-based-authorization-model-for-controller-actions-controllers-use-authorize.md (docs) - Update docs/adr/d87126b1-1707-44e1-a967-b3ed03510e7c-adopt-attribute-based-authorization-model-for-controller-actions-authorization-attributes-placed.md (docs) - Update docs/adr/789a3481-a7e9-43af-aac1-53564623b268-adopt-attribute-based-authorization-model-for-controller-actions-custom-authorization-requirements.md (docs) - Update docs/adr/753e6ac5-2d04-49b3-9c29-48bf5ef452fb-adopt-attribute-based-authorization-model-for-controller-actions-controller-actions-that.md (docs) - Update docs/adr/8f6f9141-ac0c-48f6-8d5e-02b7e6a25e43-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-combine-multiple.md (docs) - Update docs/adr/2156771a-e379-4878-b99f-176aad22109b-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-use-allowanonymous.md (docs) - Update docs/adr/74822a96-3248-4fde-b4ba-fae354caf724-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-custom-authorization-requirements.md (docs) - Update docs/adr/3351ba53-1850-4f4d-ad66-4c82146e896a-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md (docs) - Update docs/adr/9899c5f7-96f5-47d3-824a-880f38e2b5ff-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-authorization-attributes-applied.md (docs) - Update docs/adr/981f8aa3-70d1-4704-b00a-242fa78bbfa2-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md (docs) - Update docs/adr/46a677e4-20f6-494b-a3a7-01251f967dbb-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-combine-multiple.md (docs) - Update docs/adr/dff2c838-b9c1-4a48-8adb-8c612733d23b-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-public-endpoints-that.md (docs) - Update docs/adr/7ee91a40-96b5-4068-9cbc-bfa50d5641ac-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-failures-throw.md (docs) - Update docs/adr/79299188-39e7-484d-b952-b1e8cb4262cc-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-use-icurrentcontext.md (docs) - Update docs/adr/155e3926-1c5d-48a3-bd0f-17d5c45398f1-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-apply-authorization.md (docs) - Update docs/adr/e99923c1-abac-4b79-8b4a-16a0918ab5f9-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-requirement-classes.md (docs) - Update docs/adr/358e360f-ab17-4202-b212-3da0c0c3dc5d-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-protected-controller-actions.md (docs) - Update docs/adr/1f053f1e-a6ad-4c43-a3dc-e069331b9ca5-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-additional-authorization-checks.md (docs) - Update docs/adr/447141c6-c7e6-48b8-9ea6-daefae21dc4b-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-endpoints-that-allow.md (docs) - Update docs/adr/db813764-d050-4876-94d4-0e28cba2b6e0-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-requirements-named.md (docs) - Update docs/adr/de8d2acb-b47a-439b-a60e-efe4b11cee60-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-controllers-use-base.md (docs) - Update docs/adr/b69528d8-c594-445d-b5fb-9410756a89c7-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-typed-requirement-classes.md (docs) - Update docs/adr/9af66387-57a0-4867-861d-db50c047a087-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-attributes-placed.md (docs) - Update docs/adr/9b4c7f7c-92f0-4916-9cd1-03d66a263b7e-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-adminconsole-controller-endpoints.md (docs) - Update docs/adr/05a53096-c159-4325-aee5-9c6a1acd88df-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-public-endpoints-that.md (docs) - Update docs/adr/25e3448a-34bf-4fa3-bbdb-5cfa75a9a738-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controllers-managing-related.md (docs) - Update docs/adr/992104d8-afad-416b-b1a2-d79762911a30-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-attributes-use.md (docs) - Update docs/adr/1aa263f5-bb5a-4c72-9391-5470aed03a1c-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controller-actions-not.md (docs) - Update docs/adr/3c805701-1aa6-4179-a7ab-df1380c5fa57-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-requirements-declared.md (docs) - Update docs/adr/e0ea0450-c5af-4e11-a0b5-871bc1543346-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-internal-controller-actions.md (docs) - Update docs/adr/79e85707-b8a9-497c-9cdc-d3444434f00d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-use-multiple.md (docs) - Update docs/adr/6a8737dc-387f-416a-afe6-4d35b3083143-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-checks-occur.md (docs) - Update docs/adr/19153cc8-fd17-4cdd-b627-3b7a111b4fe4-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-separate-read.md (docs) - Update docs/adr/9860d08f-ad1a-48b1-8d99-3c3dfff6f9c7-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-self-modification-operations.md (docs) - Update docs/adr/0144da07-6cd7-45ba-9cd7-f0584aa34ead-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-apply-custom.md (docs) - Update docs/adr/a3f292d1-1cab-4f76-991e-4a83fba87e42-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-failures-authorizeasync.md (docs) - Update docs/adr/9595cb10-0420-4f1a-8b54-84969f09ad4d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-endpoints-modifying-collection.md (docs) - Update docs/adr/60f4f273-53c2-4a31-b733-f88485f7d07b-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-bit-adminconsole.md (docs) - Update docs/adr/e4b39357-d928-4adb-b122-794be886cc4b-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-read-only-collection.md (docs) - Update docs/adr/b5aa68ab-f345-4b09-b35f-327118015892-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-self-modification-operations.md (docs) - Update docs/adr/e334b687-3e75-4f83-9416-0376bf123735-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-requirements-enforced.md (docs) - Update docs/adr/e782046c-a190-4db5-9ebc-3191004e3b34-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-controllers-use-iauthorizationservice.md (docs) - Update docs/adr/3ddbdebe-6c15-4864-b8f9-d988d0954a44-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-collection-access-modifications.md (docs) - Update docs/adr/d17b61a0-9737-4968-b771-1210d7cfb5a1-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-failed-authorization-checks.md (docs) - Update docs/adr/27695c88-64e9-48cb-94cb-0759a0ba7b96-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-checks-execute.md (docs) - Update docs/adr/1cc0b477-2d8d-47e4-a0b8-8cc86275aaf1-establish-http-client-boundaries-for-external-service-integration-services-register-multiple.md (docs) - Update docs/adr/a358d52b-a70b-42c1-b2aa-03d2f8fae6e1-establish-http-client-boundaries-for-external-service-integration-http-request-headers.md (docs) - Update docs/adr/7e79fd2f-f710-4f04-9d12-f46135302205-establish-http-client-boundaries-for-external-service-integration-external-client-calls.md (docs) - Update docs/adr/bc29ebf0-457a-4663-9f3e-02531612373e-establish-http-client-boundaries-for-external-service-integration-test-environments-use.md (docs) - Update docs/adr/78593eda-af88-4bd6-9784-a3e7ccb7e150-establish-http-client-boundaries-for-external-service-integration-http-clients-that.md (docs) - Update docs/adr/5dbb6704-3c65-4f9a-b03b-68cf4c7f95b9-establish-http-client-boundaries-for-external-service-integration-named-http-clients.md (docs) - Update docs/adr/d376f581-9ece-4f04-a0b9-d56ac4fa12bb-establish-http-client-boundaries-for-external-service-integration-external-http-client.md (docs) - Update docs/adr/916751b2-b271-443c-9795-004adff9f00b-enforce-authorization-service-pattern-for-access-control-decisions-test-environments-use.md (docs) - Update docs/adr/d6b99429-7694-4bb1-831c-eeb84b33654c-enforce-authorization-service-pattern-for-access-control-decisions-bulk-operations-verify.md (docs) - Update docs/adr/fcd63002-33ef-4693-9995-de547f45589e-enforce-authorization-service-pattern-for-access-control-decisions-custom-authorization-requirements.md (docs) - Update docs/adr/4a4909d9-8d78-44fe-9b7e-a3dbe089be24-enforce-authorization-service-pattern-for-access-control-decisions-authorization-policies-configured.md (docs) - Update docs/adr/5a99a8f6-738b-4a0c-8d4b-af692c7977fb-enforce-authorization-service-pattern-for-access-control-decisions-authorization-failures-throw.md (docs) - Update docs/adr/aa269035-dd58-4901-be93-7ced95cd3b0c-enforce-authorization-service-pattern-for-access-control-decisions-controllers-inject-iauthorizationservice.md (docs) - Update docs/adr/781f6b28-4c7f-4deb-817d-762221188c8c-enforce-authorization-service-pattern-for-access-control-decisions-authorization-checks-performed.md (docs) - Update docs/adr/218891f7-9da8-4417-a739-5140c3f11a36-enforce-authorization-service-pattern-for-access-control-decisions-protected-controller-actions.md (docs) - Update docs/adr/1a73e7c0-65d3-440c-b1eb-3c8d3997c31f-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-combine-declarative.md (docs) - Update docs/adr/a1e870a0-0dc1-4fe8-a9cf-2fac8e888b6e-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-test-environments-configure.md (docs) - Update docs/adr/94d3fff7-cc0a-47a0-bd13-0d957a5de9fb-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-policies-registered.md (docs) - Update docs/adr/cdc85dc0-fd41-44d2-a677-7ccca2beebe1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-throw-notfoundexception.md (docs) - Update docs/adr/d1075a6d-f799-4490-b756-78ce09ef24d0-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-checks-call.md (docs) - Update docs/adr/d74bb1a6-73ee-4c6e-bdbb-ad4d548547b1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-inject-iauthorizationservice.md (docs) - Update docs/adr/77bc5fcb-f89e-4ff6-abb4-4d1494ae4c74-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-protected-controller-endpoints.md (docs) - Update docs/adr/94de471a-d3c3-4311-9187-13e91cebe0f2-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-exception-handling-tests.md (docs) - Update docs/adr/e6596a48-53e0-4b58-9297-172d935261dd-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-async.md (docs) - Update docs/adr/d7303975-2017-4fe8-90bb-4a566464eef6-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-cover-both.md (docs) - Update docs/adr/de1c22f9-d8ba-4eca-bb3e-ea5d64b8e226-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-that.md (docs) - Update docs/adr/8bf3971d-2183-4106-bb02-1d737379e42a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-validate-operation.md (docs) - Update docs/adr/eeeb0b67-297d-4d5d-be90-ca0ff7011f0a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-query.md (docs) - Update docs/adr/eab0181a-1b33-4cfc-bfab-97f8aaf0ef10-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-dependency.md (docs) - Update docs/adr/8f9885e8-0c25-422f-9a77-cf407a73f7b0-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-unit-tests-query.md (docs) - Update docs/adr/ad5d08c9-8728-47e5-b261-fa5e075ee348-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-linq.md (docs) - Update docs/adr/79b476ff-5365-46ea-b2b7-01b630ab12c9-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-fixture-setup.md (docs) - Update docs/adr/557fb6ef-5a71-4648-9beb-9a4d6f0504c2-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verify-asynchronous.md (docs) - Update docs/adr/b50c1537-803a-4460-8c5d-49b40744ec96-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-received.md (docs) - Update docs/adr/de9f504d-885a-43ed-b247-3dfd6643354a-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verifying-exceptions.md (docs) - Update docs/adr/9dfa9d4e-39bb-4768-b815-2b42f885a25f-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-methods-that.md (docs) - Update docs/adr/b65c1be4-a418-4582-bdb0-f734ba86efc4-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-combine.md (docs) - Update docs/adr/f25d68ac-56d9-4222-93c1-b739d5abcf7e-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-middleware-added.md (docs) - Update docs/adr/bd635931-0c61-4030-8a96-afebe0b1149c-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-test-environments-define.md (docs) - Update docs/adr/4edbda29-90a0-4c8a-97b6-e7a0bb5e58dd-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-named.md (docs) - Update docs/adr/f6bde425-ff4b-4ba8-9610-7c913f3a12ec-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-scim-endpoint-authorization.md (docs) - Update docs/adr/a09e8e4e-72c4-4cdf-9532-4356d0da43a2-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-production-authorization-policies.md (docs) - Update docs/adr/b7a378ff-2230-4630-bcae-4b368ef2174f-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-registered.md (docs) - Update docs/adr/17646b12-9b44-429d-8cda-26504ef06142-adopt-api-key-authentication-scheme-for-scim-service-endpoints-integration-test-factories.md (docs) - Update docs/adr/58ef2725-e19b-493e-9a95-7b5c168213cf-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-schemes.md (docs) - Update docs/adr/f2603862-ba99-4ae7-bc7e-0252d4ad11ab-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-middleware-registered.md (docs) - Update docs/adr/d009f0b4-3905-4624-80b9-2ca46f364016-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-handlers.md (docs) - Update docs/adr/0cb98c9c-8648-4035-b801-527526b20ada-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authorization-policies-require.md (docs) - Update docs/adr/76ba54b2-0ca8-4aca-b2e1-b8c4cce7f095-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-handlers-inherit.md (docs) - Update docs/adr/f9a4858e-ea4a-426c-bb8e-6fc3a10fb197-adopt-api-key-authentication-scheme-for-scim-service-endpoints-scim-service-endpoints.md (docs) - Update docs/adr/171a2ff9-448e-44ad-aea6-5b5acdfde617-standardize-authorization-policy-configuration-with-named-scopes-authentication-scheme-configuration.md (docs) - Update docs/adr/14d355fa-4151-47ec-be57-af33dec27278-standardize-authorization-policy-configuration-with-named-scopes-named-authorization-policies.md (docs) - Update docs/adr/925c710e-4e51-42f8-8fc3-06b61c142cdd-standardize-authorization-policy-configuration-with-named-scopes-authorization-configuration-applied.md (docs) - Update docs/adr/f608c3ab-b657-400c-b7e6-9bea9ad78794-standardize-authorization-policy-configuration-with-named-scopes-test-environments-use.md (docs) - Update docs/adr/bd9c0591-a386-4d5e-a80d-763893e0e961-standardize-authorization-policy-configuration-with-named-scopes-scope-based-authorization.md (docs) - Update docs/adr/0d1f5b18-b490-49be-8e39-8faaa1e2424f-standardize-authorization-policy-configuration-with-named-scopes-production-authorization-policies.md (docs) - Update docs/adr/dbd8aab1-ab4a-4f5a-8ffb-becc2a19bfa1-standardize-authorization-policy-configuration-with-named-scopes-authorization-policies-configured.md (docs) - Update docs/adr/54636413-d057-4d7a-a8d4-19e29618dc76-enforce-authorization-via-policy-based-configuration-in-scim-services-domain-business-logic.md (docs) - Update docs/adr/ef9da943-1527-4e31-a94f-b20de8163e9c-enforce-authorization-via-policy-based-configuration-in-scim-services-authentication-schemes-configured.md (docs) - Update docs/adr/f0941089-2e5d-43c2-8f5a-52162d5a565e-enforce-authorization-via-policy-based-configuration-in-scim-services-test-environments-use.md (docs) - Update docs/adr/7b79a03b-7943-44f6-b8a1-5dbcc0ece8b8-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-middleware-added.md (docs) - Update docs/adr/3121bce3-ebbb-40ed-92ef-7b413ac61c13-enforce-authorization-via-policy-based-configuration-in-scim-services-production-scim-policies.md (docs) - Update docs/adr/cbc17a37-2cd6-4449-a1ae-9d42f7dc45f5-enforce-authorization-via-policy-based-configuration-in-scim-services-scim-named-policy.md (docs) - Update docs/adr/fcbd71ee-73d7-435c-983b-76fc42f54448-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-policies-registered.md (docs) - Update docs/adr/f8dc926d-f900-4ef3-aae4-f2117e32e004-adopt-test-authentication-scheme-for-integration-testing-test-authentication-configuration.md (docs) - Update docs/adr/d13fb5ff-b73e-4677-8d19-7ae186771c89-adopt-test-authentication-scheme-for-integration-testing-test-claims-include.md (docs) - Update docs/adr/ba44ca4f-2765-4398-b3c4-113ea2bab4dd-adopt-test-authentication-scheme-for-integration-testing-test-authentication-schemes.md (docs) - Update docs/adr/c7780231-7bef-4325-9208-971b925b454d-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md (docs) - Update docs/adr/98aaa6a5-b1a5-4074-a5ba-5538ff2f5170-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md (docs) - Update docs/adr/bc7e164b-099b-4ba0-8e7e-c50e8ff13166-adopt-test-authentication-scheme-for-integration-testing-integration-test-projects.md (docs) - Update docs/adr/76873ea9-7582-4103-8bba-d3a38075aac8-use-system-text-json-for-scim-api-data-access-serialization-test-factories-use.md (docs) - Update docs/adr/d2712e9d-1ee5-4a6a-be5b-b080bbbc34e6-use-system-text-json-for-scim-api-data-access-serialization-http-requests-scim.md (docs) - Update docs/adr/9daa4246-124f-4135-8383-599b5cb24aba-use-system-text-json-for-scim-api-data-access-serialization-test-authentication-handlers.md (docs) - Update docs/adr/1acafa6d-8d2f-49da-8c36-0b8c136c602f-use-system-text-json-for-scim-api-data-access-serialization-data-access-operations.md (docs) - Update docs/adr/2eb105ee-ef02-4462-9a0f-7284bb1c2b10-use-system-text-json-for-scim-api-data-access-serialization-json-serialization-use.md (docs) - Update docs/adr/c5f8d2c9-7e8d-44e2-8502-2f67bf280239-use-system-text-json-for-scim-api-data-access-serialization-scim-integration-tests.md (docs) - Update docs/adr/9e7ca0aa-4dab-4df2-bc68-8b163f841d29-register-core-infrastructure-services-via-dependency-injection-container-test-authentication-handlers.md (docs) - Update docs/adr/69102dad-97f7-491e-88fe-9133675beb97-register-core-infrastructure-services-via-dependency-injection-container-authorization-policies-use.md (docs) - Update docs/adr/aab5279c-67a4-460e-827a-dedceac4a97e-register-core-infrastructure-services-via-dependency-injection-container-service-registration-occur.md (docs) - Update docs/adr/a82901b9-0179-442c-841a-6b741dd1b9f5-register-core-infrastructure-services-via-dependency-injection-container-authentication-schemes-registered.md (docs) - Update docs/adr/a3851f8b-cb87-4a32-b0f2-afcdd5864124-register-core-infrastructure-services-via-dependency-injection-container-test-environments-register.md (docs) - Update docs/adr/9d841473-59fe-4b92-a6a2-5a70f8f090b4-register-core-infrastructure-services-via-dependency-injection-container-infrastructure-services-registered.md (docs) - Update docs/adr/9f5d3eea-eccf-4e82-aef9-dbc13844e4ae-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-tests-append-custom.md (docs) - Update docs/adr/716f591a-8197-4b3a-9b4e-8289d3220344-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-servers-inject.md (docs) - Update docs/adr/98164f52-434e-46c9-af87-18909877ff3f-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-authorization-policies.md (docs) - Update docs/adr/39443d4c-df3a-4eb5-87de-4a7f1c7d774a-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-scim-endpoint-tests.md (docs) - Update docs/adr/fdb27347-e3f0-49f2-a5db-da80b3eab9d3-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-factories-configure.md (docs) - Update docs/adr/f5ec24ef-0f13-4808-a252-ebb15c6726e0-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-integration-tests-call.md (docs) --- ...ng-additional-authorization-checks-1f05.md | 30 +++++ ...tting-additional-cryptographic-key-c744.md | 38 ++++++ ...ting-additional-diagnostic-context-304d.md | 36 +++++ ...cross-cutting-additional-fake-keys-c692.md | 49 +++++++ ...-adminconsole-controller-endpoints-9b4c.md | 40 ++++++ ...tting-authentication-failure-tests-625a.md | 37 +++++ ...ng-authentication-handlers-inherit-76ba.md | 43 ++++++ ...thentication-middleware-registered-f260.md | 39 ++++++ ...uthentication-scheme-configuration-171a.md | 31 +++++ ...-authentication-schemes-configured-ef9d.md | 37 +++++ ...-authentication-schemes-registered-a829.md | 29 ++++ ...g-authorization-attributes-applied-9899.md | 37 +++++ ...ng-authorization-attributes-placed-9af6.md | 30 +++++ ...ng-authorization-attributes-placed-d871.md | 36 +++++ ...tting-authorization-attributes-use-9921.md | 29 ++++ ...-cutting-authorization-checks-call-d107.md | 34 +++++ ...tting-authorization-checks-execute-2769.md | 38 ++++++ ...cutting-authorization-checks-occur-6a87.md | 31 +++++ ...ing-authorization-checks-performed-781f.md | 31 +++++ ...uthorization-configuration-applied-925c.md | 42 ++++++ ...horization-failures-authorizeasync-a3f2.md | 37 +++++ ...tting-authorization-failures-throw-5a99.md | 29 ++++ ...tting-authorization-failures-throw-7ee9.md | 36 +++++ ...ss-cutting-authorization-logic-not-ca94.md | 37 +++++ ...ing-authorization-middleware-added-7b79.md | 38 ++++++ ...ing-authorization-middleware-added-f25d.md | 42 ++++++ ...ing-authorization-policies-combine-b65c.md | 35 +++++ ...-authorization-policies-configured-4a49.md | 32 +++++ ...-authorization-policies-configured-dbd8.md | 41 ++++++ ...tting-authorization-policies-named-4edb.md | 34 +++++ ...-authorization-policies-registered-94d3.md | 42 ++++++ ...-authorization-policies-registered-b7a3.md | 44 ++++++ ...-authorization-policies-registered-fcbd.md | 36 +++++ ...ing-authorization-policies-require-0cb9.md | 40 ++++++ ...cutting-authorization-policies-use-6910.md | 29 ++++ ...-authorization-requirement-classes-2368.md | 40 ++++++ ...-authorization-requirement-classes-e999.md | 41 ++++++ ...authorization-requirements-billing-3f88.md | 34 +++++ ...uthorization-requirements-declared-3c80.md | 30 +++++ ...uthorization-requirements-enforced-e334.md | 36 +++++ ...g-authorization-requirements-named-db81.md | 31 +++++ ...g-authorization-verification-tests-2daa.md | 30 +++++ ...s-cutting-base64-encoding-decoding-0aee.md | 38 ++++++ ...oss-cutting-billing-endpoints-that-b5d9.md | 35 +++++ ...ing-boundaries-coordinate-multiple-7266.md | 29 ++++ ...ross-cutting-build-scripts-declare-d7c8.md | 29 ++++ ...oss-cutting-bulk-operations-verify-d6b9.md | 34 +++++ ...ting-cache-configuration-integrate-4625.md | 38 ++++++ ...ss-cutting-cache-configuration-use-49c3.md | 41 ++++++ ...ss-cutting-cache-configuration-use-f590.md | 39 ++++++ ...tting-cache-implementations-expose-f10e.md | 35 +++++ ...-cutting-cache-implementations-use-92c0.md | 38 ++++++ ...ng-cache-registration-encapsulated-b774.md | 37 +++++ ...cutting-cache-service-registration-1246.md | 30 +++++ ...cutting-cache-service-registration-175e.md | 29 ++++ ...cutting-cache-service-registration-2dcf.md | 31 +++++ ...cutting-cache-service-registration-46f7.md | 35 +++++ ...cutting-cache-service-registration-b5a1.md | 30 +++++ ...ng-collection-access-modifications-3ddb.md | 37 +++++ ...ss-cutting-context-classes-include-80d4.md | 31 +++++ ...-cutting-controller-action-methods-3351.md | 37 +++++ ...-cutting-controller-action-methods-981f.md | 34 +++++ ...oss-cutting-controller-actions-not-1aa2.md | 30 +++++ ...ss-cutting-controller-actions-that-753e.md | 37 +++++ ...ng-controllers-apply-authorization-155e.md | 37 +++++ ...s-cutting-controllers-apply-custom-0144.md | 29 ++++ ...g-controllers-authorize-attributes-3853.md | 29 ++++ ...tting-controllers-bit-adminconsole-60f4.md | 30 +++++ ...ss-cutting-controllers-bit-billing-446f.md | 35 +++++ ...ng-controllers-combine-declarative-1a73.md | 42 ++++++ ...tting-controllers-combine-multiple-46a6.md | 32 +++++ ...tting-controllers-combine-multiple-8f6f.md | 30 +++++ ...tting-controllers-handle-aggregate-730e.md | 36 +++++ ...ting-controllers-handling-external-8ed8.md | 29 ++++ ...oss-cutting-controllers-have-class-100f.md | 30 +++++ ...llers-inject-iauthorizationservice-aa26.md | 31 +++++ ...llers-inject-iauthorizationservice-d74b.md | 42 ++++++ ...-cutting-controllers-log-operation-b1e7.md | 30 +++++ ...cutting-controllers-log-successful-0929.md | 29 ++++ ...tting-controllers-managing-related-25e3.md | 30 +++++ ...-cutting-controllers-separate-read-1915.md | 30 +++++ ...ontrollers-throw-notfoundexception-cdc8.md | 34 +++++ ...ing-controllers-use-allowanonymous-2156.md | 30 +++++ ...-cutting-controllers-use-authorize-1b71.md | 38 ++++++ ...cross-cutting-controllers-use-base-de8d.md | 38 ++++++ ...trollers-use-iauthorizationservice-e782.md | 38 ++++++ ...ng-controllers-use-icurrentcontext-7929.md | 31 +++++ ...s-cutting-controllers-use-multiple-79e8.md | 31 +++++ .../cross-cutting-cross-language-data-2955.md | 35 +++++ .../cross-cutting-cross-language-ffi-ab20.md | 34 +++++ ...ng-cryptographic-components-cipher-bbc8.md | 37 +++++ ...tting-cryptographic-key-generation-b56a.md | 37 +++++ ...tting-cryptographic-key-generation-fbc0.md | 37 +++++ ...cutting-cryptographic-key-material-893a.md | 37 +++++ ...ss-cutting-cryptographic-key-types-93ca.md | 38 ++++++ ...ng-cryptographic-operations-cipher-f6f6.md | 50 +++++++ ...cryptographic-operations-involving-e4ca.md | 38 ++++++ ...cutting-cryptographic-types-cipher-8303.md | 38 ++++++ ...ng-csbindgen-configuration-specify-8c53.md | 29 ++++ ...cutting-cstr-conversions-performed-7c7f.md | 35 +++++ ...ss-cutting-cstr-string-conversions-205a.md | 36 +++++ ...-custom-authorization-requirements-7482.md | 38 ++++++ ...-custom-authorization-requirements-789a.md | 37 +++++ ...-custom-authorization-requirements-fcd6.md | 31 +++++ .../cross-cutting-custom-result-types-8332.md | 31 +++++ ...oss-cutting-custom-result-wrappers-23bd.md | 30 +++++ ...oss-cutting-data-access-operations-1aca.md | 31 +++++ ...oss-cutting-data-access-operations-44b0.md | 34 +++++ ...cutting-dbset-properties-organized-86b1.md | 30 +++++ ...cross-cutting-dbset-property-names-613d.md | 29 ++++ ...ross-cutting-dedicated-free-string-5122.md | 36 +++++ ...-distributed-cache-implementations-7a7e.md | 36 +++++ ...istributed-caching-implementations-859c.md | 33 +++++ ...ross-cutting-domain-business-logic-5463.md | 34 +++++ .../rules/cross-cutting-each-fake-rsa-889f.md | 37 +++++ .../rules/cross-cutting-each-fake-rsa-9e21.md | 36 +++++ ...ing-endpoints-modifying-collection-9595.md | 31 +++++ ...cross-cutting-endpoints-that-allow-4471.md | 30 +++++ ...cutting-entity-framework-dbcontext-abc6.md | 30 +++++ ...oss-cutting-entity-types-requiring-8ef3.md | 37 +++++ .../cross-cutting-error-log-entries-5cd6.md | 29 ++++ ...s-cutting-exception-handling-tests-94de.md | 31 +++++ ...s-cutting-exception-logging-within-5e08.md | 29 ++++ ...s-cutting-extended-cache-utilities-aaaf.md | 41 ++++++ ...ross-cutting-external-client-calls-7e79.md | 34 +++++ ...cross-cutting-external-http-client-d376.md | 33 +++++ ...s-cutting-external-service-clients-a488.md | 30 +++++ ...utting-failed-authorization-checks-d17b.md | 37 +++++ ...oss-cutting-fake-cryptographic-key-ace5.md | 29 ++++ .../rules/cross-cutting-fake-rsa-key-229c.md | 36 +++++ .../rules/cross-cutting-fake-rsa-key-2471.md | 35 +++++ .../rules/cross-cutting-fake-rsa-key-bfc4.md | 35 +++++ .../rules/cross-cutting-fake-rsa-key-cbea.md | 35 +++++ .../rules/cross-cutting-fake-rsa-key-fffb.md | 36 +++++ .../rules/cross-cutting-fake-rsa-keys-15e4.md | 41 ++++++ .../rules/cross-cutting-fake-rsa-keys-3f21.md | 42 ++++++ .../rules/cross-cutting-fake-rsa-keys-af1e.md | 37 +++++ ...oss-cutting-ffi-boundary-functions-918a.md | 32 +++++ ...ss-cutting-ffi-boundary-validation-d076.md | 31 +++++ ...ss-cutting-ffi-boundary-validation-f057.md | 35 +++++ .../cross-cutting-ffi-entry-points-dcb8.md | 43 ++++++ ...-cutting-ffi-exposed-cryptographic-b670.md | 40 ++++++ ...ss-cutting-ffi-functions-accepting-0ca0.md | 31 +++++ ...ss-cutting-ffi-functions-accepting-2b77.md | 35 +++++ ...ss-cutting-ffi-functions-accepting-aff1.md | 40 ++++++ ...ss-cutting-ffi-functions-accepting-bf2a.md | 37 +++++ .../cross-cutting-ffi-functions-not-5d4a.md | 37 +++++ ...cross-cutting-ffi-functions-return-7a63.md | 30 +++++ ...cross-cutting-ffi-functions-return-d4fe.md | 35 +++++ ...ss-cutting-ffi-functions-returning-07be.md | 34 +++++ ...ss-cutting-ffi-functions-returning-b569.md | 34 +++++ ...ss-cutting-ffi-functions-returning-daae.md | 37 +++++ ...ss-cutting-ffi-functions-returning-f766.md | 37 +++++ .../cross-cutting-ffi-functions-that-ed1f.md | 38 ++++++ .../cross-cutting-ffi-functions-use-1f6f.md | 35 +++++ .../cross-cutting-ffi-functions-use-4489.md | 35 +++++ .../cross-cutting-ffi-functions-use-846b.md | 35 +++++ ...oss-cutting-ffi-functions-validate-87be.md | 36 +++++ ...cross-cutting-ffi-modules-document-9333.md | 39 ++++++ .../cross-cutting-ffi-modules-use-10d2.md | 36 +++++ .../cross-cutting-ffi-modules-use-71f1.md | 37 +++++ .../cross-cutting-ffi-modules-use-f2ec.md | 29 ++++ ...ross-cutting-ffi-string-validation-6a74.md | 35 +++++ ...ross-cutting-ffi-string-validation-d47f.md | 38 ++++++ ...cutting-generated-bindings-specify-95a4.md | 30 +++++ ...ross-cutting-hardcoded-rsa-private-4685.md | 35 +++++ .../cross-cutting-http-action-methods-a5bd.md | 31 +++++ ...cutting-http-client-configurations-b862.md | 29 ++++ ...ss-cutting-http-clients-registered-2dbc.md | 29 ++++ .../cross-cutting-http-clients-that-7859.md | 33 +++++ ...ross-cutting-http-endpoint-methods-6d08.md | 34 +++++ ...cross-cutting-http-request-headers-a358.md | 30 +++++ .../cross-cutting-http-requests-scim-d271.md | 31 +++++ .../cross-cutting-http-response-types-74bf.md | 31 +++++ ...g-implementation-suppress-specific-c43d.md | 38 ++++++ ...tting-implementations-use-resource-551e.md | 29 ++++ ...ting-include-structured-contextual-052d.md | 29 ++++ ...infrastructure-services-registered-9d84.md | 31 +++++ ...cross-cutting-input-validation-ffi-32ec.md | 34 +++++ ...cutting-integration-test-factories-1764.md | 41 ++++++ ...-cutting-integration-test-projects-bc7e.md | 39 ++++++ ...oss-cutting-integration-tests-call-f5ec.md | 35 +++++ ...-cutting-integration-tests-connect-758d.md | 41 ++++++ ...ross-cutting-integration-tests-use-d5ac.md | 40 ++++++ ...ross-cutting-integration-tests-use-ef0e.md | 35 +++++ ...utting-internal-controller-actions-e0ea.md | 30 +++++ ...oss-cutting-json-serialization-use-2eb1.md | 32 +++++ ...s-cutting-key-generation-functions-aca2.md | 46 +++++++ ...oss-cutting-key-management-modules-aaf3.md | 44 ++++++ ...cross-cutting-log-entries-failures-fb74.md | 35 +++++ .../cross-cutting-log-entries-not-bf81.md | 34 +++++ ...ss-cutting-log-exceptions-external-4360.md | 29 ++++ ...ross-cutting-log-messages-describe-7507.md | 39 ++++++ ...ross-cutting-log-messages-describe-db43.md | 30 +++++ ...ss-cutting-logger-verification-use-7680.md | 39 ++++++ ...ss-cutting-logger-verification-use-910f.md | 30 +++++ ...oss-cutting-logging-statements-use-3a5d.md | 39 ++++++ ...ting-logging-statements-validation-0931.md | 30 +++++ ...cross-cutting-memory-allocated-ffi-6520.md | 30 +++++ ...ss-cutting-modules-containing-fake-c0ec.md | 38 ++++++ .../cross-cutting-multiple-fake-key-4882.md | 29 ++++ ...tting-named-authorization-policies-14d3.md | 42 ++++++ .../cross-cutting-named-http-clients-5dbb.md | 36 +++++ ...ng-organization-billing-controller-da79.md | 35 +++++ ...ing-organization-billing-endpoints-1404.md | 34 +++++ ...ng-organization-parameters-billing-b978.md | 35 +++++ ...utting-outbound-http-communication-4af2.md | 36 +++++ ...-production-authorization-policies-0d1f.md | 45 +++++++ ...-production-authorization-policies-a09e.md | 34 +++++ ...ross-cutting-production-code-paths-c368.md | 36 +++++ ...s-cutting-production-scim-policies-3121.md | 36 +++++ ...tting-protected-controller-actions-2188.md | 32 +++++ ...tting-protected-controller-actions-358e.md | 36 +++++ ...ing-protected-controller-endpoints-77bc.md | 35 +++++ ...ross-cutting-public-endpoints-that-05a5.md | 35 +++++ ...ross-cutting-public-endpoints-that-46c1.md | 37 +++++ ...ross-cutting-public-endpoints-that-dff2.md | 40 ++++++ ...cross-cutting-public-ffi-functions-4d31.md | 36 +++++ ...cross-cutting-public-ffi-functions-d7cf.md | 34 +++++ ...cross-cutting-public-ffi-functions-fbef.md | 36 +++++ ...cutting-push-notification-services-09af.md | 30 +++++ ...cutting-push-notification-services-2769.md | 30 +++++ ...cross-cutting-read-only-collection-e4b3.md | 36 +++++ ...-cutting-redis-connection-failures-4ea5.md | 29 ++++ ...-cutting-redis-connection-failures-6ee5.md | 33 +++++ ...-cutting-redis-connection-failures-7cfd.md | 30 +++++ ...-cutting-redis-connection-failures-ffdd.md | 30 +++++ ...ting-redis-connections-established-6e7b.md | 41 ++++++ .../cross-cutting-restful-http-verbs-5544.md | 34 +++++ .../cross-cutting-result-types-expose-4249.md | 31 +++++ ...oss-cutting-result-types-implement-459e.md | 36 +++++ ...-cutting-return-fallback-responses-ecab.md | 41 ++++++ .../cross-cutting-rsa-key-operations-065c.md | 39 ++++++ .../cross-cutting-rust-sdk-modules-4738.md | 29 ++++ ...utting-scim-endpoint-authorization-f6bd.md | 33 +++++ .../cross-cutting-scim-endpoint-tests-3944.md | 35 +++++ ...oss-cutting-scim-integration-tests-c5f8.md | 31 +++++ .../cross-cutting-scim-named-policy-cbc1.md | 38 ++++++ ...oss-cutting-scim-service-endpoints-f9a4.md | 40 ++++++ ...-cutting-scope-based-authorization-bd9c.md | 29 ++++ ...tting-self-modification-operations-9860.md | 33 +++++ ...tting-self-modification-operations-b5aa.md | 37 +++++ ...tting-service-controllers-separate-385f.md | 35 +++++ ...cutting-service-registration-occur-aab5.md | 38 ++++++ ...cross-cutting-services-extend-base-95a6.md | 36 +++++ ...-cutting-services-implement-custom-e177.md | 29 ++++ ...-services-processing-notifications-c775.md | 35 +++++ ...cutting-services-register-multiple-1cc0.md | 38 ++++++ ...ing-shared-cryptographic-resources-16aa.md | 46 +++++++ ...cross-cutting-string-data-crossing-3353.md | 36 +++++ ...cutting-string-validation-failures-12ca.md | 38 ++++++ ...s-cutting-swagger-openapi-document-b183.md | 36 +++++ ...-test-authentication-configuration-f8dc.md | 44 ++++++ ...tting-test-authentication-handlers-98aa.md | 43 ++++++ ...tting-test-authentication-handlers-9daa.md | 41 ++++++ ...tting-test-authentication-handlers-9e7c.md | 40 ++++++ ...tting-test-authentication-handlers-c778.md | 44 ++++++ ...tting-test-authentication-handlers-d009.md | 45 +++++++ ...utting-test-authentication-schemes-58ef.md | 34 +++++ ...utting-test-authentication-schemes-ba44.md | 43 ++++++ ...utting-test-authorization-policies-9816.md | 35 +++++ .../cross-cutting-test-claims-include-d13f.md | 33 +++++ .../cross-cutting-test-code-define-c095.md | 40 ++++++ ...cross-cutting-test-code-exercising-1293.md | 36 +++++ .../cross-cutting-test-code-requiring-7fee.md | 40 ++++++ .../rules/cross-cutting-test-code-use-30b7.md | 35 +++++ ...utting-test-environments-configure-a1e8.md | 35 +++++ ...s-cutting-test-environments-define-bd63.md | 34 +++++ ...cutting-test-environments-register-a385.md | 29 ++++ ...ross-cutting-test-environments-use-9167.md | 30 +++++ ...ross-cutting-test-environments-use-bc29.md | 31 +++++ ...ross-cutting-test-environments-use-f094.md | 31 +++++ ...ross-cutting-test-environments-use-f608.md | 45 +++++++ ...s-cutting-test-factories-configure-fdb2.md | 35 +++++ .../cross-cutting-test-factories-use-7687.md | 40 ++++++ .../cross-cutting-test-fixture-setup-79b4.md | 46 +++++++ ...utting-test-fixtures-cryptographic-562a.md | 29 ++++ ...ss-cutting-test-fixtures-requiring-be91.md | 36 +++++ .../cross-cutting-test-fixtures-use-2eaa.md | 39 ++++++ .../cross-cutting-test-helpers-report-03d0.md | 30 +++++ .../cross-cutting-test-methods-that-9dfa.md | 38 ++++++ .../cross-cutting-test-servers-inject-716f.md | 38 ++++++ .../cross-cutting-test-suites-include-f3f0.md | 36 +++++ ...ross-cutting-test-suites-requiring-a086.md | 40 ++++++ .../cross-cutting-tests-append-custom-9f5d.md | 36 +++++ ...cutting-tests-assert-jsonvaluekind-54d7.md | 33 +++++ .../cross-cutting-tests-cover-both-d730.md | 44 ++++++ ...oss-cutting-tests-use-asserthelper-e296.md | 41 ++++++ .../cross-cutting-tests-use-async-e659.md | 31 +++++ ...cross-cutting-tests-use-dependency-eab0.md | 39 ++++++ .../cross-cutting-tests-use-linq-ad5d.md | 45 +++++++ .../cross-cutting-tests-use-received-b50c.md | 38 ++++++ ...s-cutting-tests-validate-operation-8bf3.md | 40 ++++++ ...utting-tests-validating-successful-1a26.md | 40 ++++++ ...-cutting-tests-verify-asynchronous-557f.md | 45 +++++++ .../cross-cutting-tests-verify-number-61b8.md | 31 +++++ .../cross-cutting-tests-verify-query-eeeb.md | 40 ++++++ ...ross-cutting-tests-verify-specific-0346.md | 36 +++++ .../cross-cutting-tests-verify-that-de1c.md | 31 +++++ ...cutting-tests-verifying-exceptions-de9f.md | 36 +++++ ...-cutting-typed-requirement-classes-b695.md | 40 ++++++ .../cross-cutting-unit-tests-query-8f98.md | 41 ++++++ .../cross-cutting-unit-tests-use-bee1.md | 35 +++++ .../cross-cutting-unit-tests-verify-d040.md | 39 ++++++ .../cross-cutting-use-logerror-level-2e07.md | 36 +++++ ...ross-cutting-wrap-external-service-ce6b.md | 39 ++++++ AGENTS.md | 55 ++++++++ CLAUDE.md | 55 ++++++++ ...ser-operations-controllers-apply-custom.md | 122 +++++++++++++++++ ...bility-components-tests-verify-specific.md | 116 ++++++++++++++++ ...lers-via-unit-tests-test-helpers-report.md | 120 +++++++++++++++++ ...-failures-include-structured-contextual.md | 117 ++++++++++++++++ ...nal-api-endpoints-public-endpoints-that.md | 118 ++++++++++++++++ ...nagement-in-rust-sdk-rsa-key-operations.md | 114 ++++++++++++++++ ...ring-conversion-ffi-functions-returning.md | 123 +++++++++++++++++ ...-controllers-controllers-log-successful.md | 117 ++++++++++++++++ ...-services-logging-statements-validation.md | 116 ++++++++++++++++ ...ush-services-push-notification-services.md | 116 ++++++++++++++++ ...on-in-rust-sdk-base64-encoding-decoding.md | 119 ++++++++++++++++ ...ing-conversions-ffi-functions-accepting.md | 121 +++++++++++++++++ ...ndpoints-authorization-policies-require.md | 125 +++++++++++++++++ ...copes-production-authorization-policies.md | 117 ++++++++++++++++ ...s-via-unit-tests-controllers-have-class.md | 120 +++++++++++++++++ ...p-transfer-for-rust-sdk-ffi-modules-use.md | 121 +++++++++++++++++ ...ibuted-cache-cache-service-registration.md | 113 ++++++++++++++++ ...blic-api-protocols-test-code-exercising.md | 121 +++++++++++++++++ ...-in-rust-sdk-string-validation-failures.md | 122 +++++++++++++++++ ...erations-organization-billing-endpoints.md | 115 ++++++++++++++++ ...med-scopes-named-authorization-policies.md | 117 ++++++++++++++++ ...actions-controllers-apply-authorization.md | 126 +++++++++++++++++ ...ting-public-api-protocols-fake-rsa-keys.md | 121 +++++++++++++++++ ...rust-sdk-shared-cryptographic-resources.md | 117 ++++++++++++++++ ...pes-authentication-scheme-configuration.md | 117 ++++++++++++++++ ...api-contract-cache-service-registration.md | 113 ++++++++++++++++ ...ce-endpoints-integration-test-factories.md | 125 +++++++++++++++++ ...er-operations-controllers-separate-read.md | 122 +++++++++++++++++ ...ation-tests-tests-validating-successful.md | 117 ++++++++++++++++ ...service-controllers-combine-declarative.md | 126 +++++++++++++++++ ...al-api-endpoints-controller-actions-not.md | 118 ++++++++++++++++ ...ss-serialization-data-access-operations.md | 115 ++++++++++++++++ ...oller-actions-controllers-use-authorize.md | 127 ++++++++++++++++++ ...-integration-services-register-multiple.md | 121 +++++++++++++++++ ...ization-additional-authorization-checks.md | 121 +++++++++++++++++ ...transfer-for-rust-sdk-ffi-functions-use.md | 121 +++++++++++++++++ ...ring-conversion-cstr-string-conversions.md | 123 +++++++++++++++++ ...trollers-controllers-use-allowanonymous.md | 123 +++++++++++++++++ ...-decisions-protected-controller-actions.md | 126 +++++++++++++++++ ...g-cryptographic-operations-fake-rsa-key.md | 125 +++++++++++++++++ ...tions-authorization-requirement-classes.md | 127 ++++++++++++++++++ ...onse-abstraction-custom-result-wrappers.md | 116 ++++++++++++++++ ...nts-with-naming-convention-fake-rsa-key.md | 124 +++++++++++++++++ ...-endpoints-controllers-managing-related.md | 118 ++++++++++++++++ ...ush-services-push-notification-services.md | 116 ++++++++++++++++ ...operations-authorization-checks-execute.md | 124 +++++++++++++++++ ...-framework-contexts-cross-language-data.md | 113 ++++++++++++++++ ...ion-in-rust-sdk-ffi-functions-accepting.md | 119 ++++++++++++++++ ...-tests-authorization-verification-tests.md | 120 +++++++++++++++++ ...ice-integration-http-clients-registered.md | 115 ++++++++++++++++ ...api-contract-cache-service-registration.md | 113 ++++++++++++++++ ...nal-service-failures-use-logerror-level.md | 117 ++++++++++++++++ ...tr-cstring-conversion-test-fixtures-use.md | 123 +++++++++++++++++ ...ss-serialization-json-serialization-use.md | 115 ++++++++++++++++ ...xtensions-additional-diagnostic-context.md | 100 ++++++++++++++ ...-cryptographic-operations-test-code-use.md | 125 +++++++++++++++++ ...-scim-services-production-scim-policies.md | 121 +++++++++++++++++ ...interop-boundaries-input-validation-ffi.md | 116 ++++++++++++++++ ...e-controllers-controller-action-methods.md | 123 +++++++++++++++++ ...nsfer-for-rust-sdk-string-data-crossing.md | 121 +++++++++++++++++ ...er-actions-protected-controller-actions.md | 126 +++++++++++++++++ ...ollers-controllers-authorize-attributes.md | 117 ++++++++++++++++ ...boundaries-service-controllers-separate.md | 102 ++++++++++++++ ...m-integration-tests-scim-endpoint-tests.md | 113 ++++++++++++++++ ...cache-extensions-logging-statements-use.md | 100 ++++++++++++++ ...nts-authorization-requirements-declared.md | 118 ++++++++++++++++ ...rations-collection-access-modifications.md | 124 +++++++++++++++++ ...ting-public-api-protocols-fake-rsa-keys.md | 121 +++++++++++++++++ ...ions-authorization-requirements-billing.md | 115 ++++++++++++++++ ...esponse-abstraction-result-types-expose.md | 116 ++++++++++++++++ ...ervice-failures-log-exceptions-external.md | 117 ++++++++++++++++ ...ling-operations-controllers-bit-billing.md | 115 ++++++++++++++++ ...-api-authorization-endpoints-that-allow.md | 121 +++++++++++++++++ ...-c-string-conversions-ffi-functions-use.md | 121 +++++++++++++++++ ...e-api-boundaries-data-access-operations.md | 102 ++++++++++++++ ...onse-abstraction-result-types-implement.md | 116 ++++++++++++++++ ...-contract-cache-configuration-integrate.md | 113 ++++++++++++++++ ...naming-convention-hardcoded-rsa-private.md | 124 +++++++++++++++++ ...er-actions-controllers-combine-multiple.md | 126 +++++++++++++++++ ...ontroller-actions-public-endpoints-that.md | 127 ++++++++++++++++++ ...e-extensions-cache-service-registration.md | 100 ++++++++++++++ ...r-rust-sdk-public-apis-rust-sdk-modules.md | 121 +++++++++++++++++ ...-rust-sdk-public-apis-multiple-fake-key.md | 121 +++++++++++++++++ ...stributed-cache-cache-configuration-use.md | 113 ++++++++++++++++ ...sions-authorization-policies-configured.md | 126 +++++++++++++++++ ...integration-outbound-http-communication.md | 115 ++++++++++++++++ ...nsfer-for-rust-sdk-public-ffi-functions.md | 121 +++++++++++++++++ ...-api-contract-redis-connection-failures.md | 113 ++++++++++++++++ ...p-net-core-authorization-policies-named.md | 126 +++++++++++++++++ ...sfer-for-rust-sdk-dedicated-free-string.md | 121 +++++++++++++++++ ...-in-scim-services-domain-business-logic.md | 121 +++++++++++++++++ ...ration-tests-tests-assert-jsonvaluekind.md | 117 ++++++++++++++++ ...onversions-implementations-use-resource.md | 121 +++++++++++++++++ ...rvice-api-boundaries-restful-http-verbs.md | 102 ++++++++++++++ ...ting-strategy-tests-verify-asynchronous.md | 113 ++++++++++++++++ ...public-apis-test-fixtures-cryptographic.md | 121 +++++++++++++++++ ...e-endpoints-test-authentication-schemes.md | 125 +++++++++++++++++ ...-decisions-authorization-failures-throw.md | 126 +++++++++++++++++ ...uted-cache-extensions-error-log-entries.md | 100 ++++++++++++++ ...onversion-in-rust-sdk-ffi-functions-not.md | 122 +++++++++++++++++ ...-service-integration-named-http-clients.md | 121 +++++++++++++++++ ...in-controllers-exception-logging-within.md | 117 ++++++++++++++++ ...operations-controllers-bit-adminconsole.md | 122 +++++++++++++++++ ...framework-contexts-dbset-property-names.md | 113 ++++++++++++++++ ...vability-components-tests-verify-number.md | 116 ++++++++++++++++ ...tion-tests-authentication-failure-tests.md | 117 ++++++++++++++++ ...ersion-in-rust-sdk-memory-allocated-ffi.md | 122 +++++++++++++++++ ...on-container-authorization-policies-use.md | 103 ++++++++++++++ ...rsion-in-rust-sdk-ffi-string-validation.md | 119 ++++++++++++++++ ...r-operations-authorization-checks-occur.md | 122 +++++++++++++++++ ...ce-api-boundaries-http-endpoint-methods.md | 102 ++++++++++++++ ...utilities-redis-connections-established.md | 121 +++++++++++++++++ ...che-utilities-redis-connection-failures.md | 121 +++++++++++++++++ ...m-integration-tests-test-servers-inject.md | 113 ++++++++++++++++ ...or-c-interop-boundaries-ffi-modules-use.md | 116 ++++++++++++++++ ...undaries-boundaries-coordinate-multiple.md | 102 ++++++++++++++ ...boundaries-controllers-handle-aggregate.md | 102 ++++++++++++++ ...llers-custom-authorization-requirements.md | 123 +++++++++++++++++ ...esponse-abstraction-http-response-types.md | 116 ++++++++++++++++ ...-service-failures-log-messages-describe.md | 117 ++++++++++++++++ ...troller-actions-controller-actions-that.md | 127 ++++++++++++++++++ ...gration-tests-integration-tests-connect.md | 117 ++++++++++++++++ ...lity-components-logger-verification-use.md | 116 ++++++++++++++++ ...access-serialization-test-factories-use.md | 115 ++++++++++++++++ ...dpoints-authentication-handlers-inherit.md | 125 +++++++++++++++++ ...nservice-protected-controller-endpoints.md | 126 +++++++++++++++++ ...ecisions-authorization-checks-performed.md | 126 +++++++++++++++++ ...l-service-integration-http-clients-that.md | 121 +++++++++++++++++ ...tions-custom-authorization-requirements.md | 127 ++++++++++++++++++ ...actions-controllers-use-icurrentcontext.md | 126 +++++++++++++++++ ...-in-testing-strategy-test-fixture-setup.md | 113 ++++++++++++++++ ...ser-operations-controllers-use-multiple.md | 122 +++++++++++++++++ ...interop-boundaries-ffi-functions-return.md | 116 ++++++++++++++++ ...cache-distributed-cache-implementations.md | 113 ++++++++++++++++ ...services-authorization-middleware-added.md | 121 +++++++++++++++++ ...-in-rust-sdk-cstr-conversions-performed.md | 119 ++++++++++++++++ ...he-extensions-redis-connection-failures.md | 100 ++++++++++++++ ...rvice-integration-external-client-calls.md | 121 +++++++++++++++++ ...er-actions-authorization-failures-throw.md | 126 +++++++++++++++++ ...ographic-operations-test-code-requiring.md | 125 +++++++++++++++++ ...mework-contexts-context-classes-include.md | 113 ++++++++++++++++ ...for-rust-sdk-cryptographic-types-cipher.md | 121 +++++++++++++++++ ...esponse-abstraction-custom-result-types.md | 116 ++++++++++++++++ ...onversion-in-rust-sdk-ffi-functions-use.md | 122 +++++++++++++++++ ...ies-distributed-caching-implementations.md | 121 +++++++++++++++++ ...ork-contexts-dbset-properties-organized.md | 113 ++++++++++++++++ ...tring-conversion-ffi-functions-validate.md | 123 +++++++++++++++++ ...-cryptographic-operations-each-fake-rsa.md | 125 +++++++++++++++++ ...-conversions-cryptographic-key-material.md | 121 +++++++++++++++++ ...ce-abstraction-tests-validate-operation.md | 113 ++++++++++++++++ ...ic-apis-csbindgen-configuration-specify.md | 121 +++++++++++++++++ ...ntrollers-controllers-handling-external.md | 117 ++++++++++++++++ ...amework-contexts-entity-types-requiring.md | 113 ++++++++++++++++ ...ontrollers-controllers-combine-multiple.md | 123 +++++++++++++++++ ...-interface-abstraction-unit-tests-query.md | 113 ++++++++++++++++ ...lity-components-logger-verification-use.md | 116 ++++++++++++++++ ...control-decisions-test-environments-use.md | 126 +++++++++++++++++ ...ment-in-rust-sdk-ffi-boundary-functions.md | 114 ++++++++++++++++ ...pes-authorization-configuration-applied.md | 117 ++++++++++++++++ ...che-utilities-cache-implementations-use.md | 121 +++++++++++++++++ ...cstring-conversion-ffi-modules-document.md | 123 +++++++++++++++++ ...ort-in-rust-sdk-cryptographic-key-types.md | 117 ++++++++++++++++ ...rvice-authorization-policies-registered.md | 126 +++++++++++++++++ ...ce-abstraction-exception-handling-tests.md | 113 ++++++++++++++++ ...erations-endpoints-modifying-collection.md | 122 +++++++++++++++++ ...-public-apis-generated-bindings-specify.md | 121 +++++++++++++++++ ...ublic-api-contract-services-extend-base.md | 113 ++++++++++++++++ ...ation-tests-test-authorization-policies.md | 113 ++++++++++++++++ ...e-controllers-controller-action-methods.md | 123 +++++++++++++++++ ...operations-self-modification-operations.md | 122 +++++++++++++++++ ...ollers-authorization-attributes-applied.md | 123 +++++++++++++++++ ...on-testing-test-authentication-handlers.md | 102 ++++++++++++++ ...-endpoints-authorization-attributes-use.md | 118 ++++++++++++++++ ...ization-authorization-attributes-placed.md | 121 +++++++++++++++++ ...ation-adminconsole-controller-endpoints.md | 121 +++++++++++++++++ ...iner-infrastructure-services-registered.md | 103 ++++++++++++++ ...ialization-test-authentication-handlers.md | 115 ++++++++++++++++ ...s-in-testing-strategy-test-methods-that.md | 113 ++++++++++++++++ ...ts-with-naming-convention-each-fake-rsa.md | 124 +++++++++++++++++ ...-container-test-authentication-handlers.md | 103 ++++++++++++++ ...m-integration-tests-tests-append-custom.md | 113 ++++++++++++++++ ...lic-api-protocols-test-suites-requiring.md | 121 +++++++++++++++++ ...-core-production-authorization-policies.md | 126 +++++++++++++++++ ...tionservice-test-environments-configure.md | 126 +++++++++++++++++ ...ervice-integration-http-request-headers.md | 121 +++++++++++++++++ ...on-container-test-environments-register.md | 103 ++++++++++++++ ...s-authorization-failures-authorizeasync.md | 122 +++++++++++++++++ ...ce-integration-external-service-clients.md | 115 ++++++++++++++++ ...lers-via-unit-tests-http-action-methods.md | 120 +++++++++++++++++ ...ainer-authentication-schemes-registered.md | 103 ++++++++++++++ ...ontrollers-inject-iauthorizationservice.md | 126 +++++++++++++++++ ...ache-utilities-extended-cache-utilities.md | 121 +++++++++++++++++ ...on-container-service-registration-occur.md | 103 ++++++++++++++ ...port-in-rust-sdk-key-management-modules.md | 117 ++++++++++++++++ ...-service-integration-cross-language-ffi.md | 115 ++++++++++++++++ ...ork-contexts-entity-framework-dbcontext.md | 113 ++++++++++++++++ ...rt-in-rust-sdk-key-generation-functions.md | 117 ++++++++++++++++ ...-sdk-public-apis-fake-cryptographic-key.md | 121 +++++++++++++++++ ...ions-in-testing-strategy-tests-use-linq.md | 113 ++++++++++++++++ ...ting-public-api-protocols-fake-rsa-keys.md | 121 +++++++++++++++++ ...erop-boundaries-ffi-functions-accepting.md | 116 ++++++++++++++++ ...via-unit-tests-swagger-openapi-document.md | 120 +++++++++++++++++ ...pi-boundaries-controllers-log-operation.md | 102 ++++++++++++++ ...-in-testing-strategy-tests-use-received.md | 113 ++++++++++++++++ ...erop-boundaries-ffi-functions-returning.md | 116 ++++++++++++++++ ...n-rust-sdk-cryptographic-key-generation.md | 114 ++++++++++++++++ ...ibuted-cache-cache-service-registration.md | 113 ++++++++++++++++ ...operations-self-modification-operations.md | 124 +++++++++++++++++ ...lling-operations-billing-endpoints-that.md | 115 ++++++++++++++++ ...net-core-authorization-policies-combine.md | 126 +++++++++++++++++ ...api-protocols-ffi-exposed-cryptographic.md | 121 +++++++++++++++++ ...authorization-typed-requirement-classes.md | 121 +++++++++++++++++ ...ilities-cache-registration-encapsulated.md | 121 +++++++++++++++++ ...-core-authorization-policies-registered.md | 126 +++++++++++++++++ ...-integration-http-client-configurations.md | 115 ++++++++++++++++ ...rations-organization-parameters-billing.md | 115 ++++++++++++++++ ...ion-testing-test-authentication-schemes.md | 102 ++++++++++++++ ...ust-sdk-cryptographic-components-cipher.md | 114 ++++++++++++++++ ...rvice-integration-test-environments-use.md | 121 +++++++++++++++++ ...ation-testing-integration-test-projects.md | 102 ++++++++++++++ ...n-asp-net-core-test-environments-define.md | 126 +++++++++++++++++ ...-named-scopes-scope-based-authorization.md | 117 ++++++++++++++++ ...phic-operations-test-fixtures-requiring.md | 125 +++++++++++++++++ ...ntrollers-via-unit-tests-unit-tests-use.md | 120 +++++++++++++++++ ...ion-in-rust-sdk-ffi-functions-accepting.md | 122 +++++++++++++++++ ...r-and-admin-controllers-log-entries-not.md | 117 ++++++++++++++++ ...nts-with-naming-convention-fake-rsa-key.md | 124 +++++++++++++++++ ...with-naming-convention-test-code-define.md | 124 +++++++++++++++++ ...ming-convention-modules-containing-fake.md | 124 +++++++++++++++++ ...naming-convention-production-code-paths.md | 124 +++++++++++++++++ ...rvices-implementation-suppress-specific.md | 116 ++++++++++++++++ ...ss-serialization-scim-integration-tests.md | 115 ++++++++++++++++ ...blic-api-protocols-additional-fake-keys.md | 121 +++++++++++++++++ ...n-rust-sdk-additional-cryptographic-key.md | 114 ++++++++++++++++ ...vices-services-processing-notifications.md | 116 ++++++++++++++++ ...on-testing-test-authentication-handlers.md | 102 ++++++++++++++ ...troller-actions-authorization-logic-not.md | 127 ++++++++++++++++++ ...tion-in-scim-services-scim-named-policy.md | 121 +++++++++++++++++ ...g-cryptographic-operations-fake-rsa-key.md | 125 +++++++++++++++++ ...ice-controllers-throw-notfoundexception.md | 126 +++++++++++++++++ ...-service-failures-wrap-external-service.md | 117 ++++++++++++++++ ...-endpoints-test-authentication-handlers.md | 125 +++++++++++++++++ ...ervability-components-unit-tests-verify.md | 116 ++++++++++++++++ ...ing-conversions-ffi-boundary-validation.md | 121 +++++++++++++++++ ...zationservice-authorization-checks-call.md | 126 +++++++++++++++++ ...integration-testing-test-claims-include.md | 102 ++++++++++++++ ...-operations-failed-authorization-checks.md | 124 +++++++++++++++++ ...access-serialization-http-requests-scim.md | 115 ++++++++++++++++ ...ervice-integration-external-http-client.md | 121 +++++++++++++++++ ...rsion-in-rust-sdk-ffi-string-validation.md | 122 +++++++++++++++++ ...ersion-in-rust-sdk-ffi-functions-return.md | 119 ++++++++++++++++ ...integration-tests-integration-tests-use.md | 117 ++++++++++++++++ ...ontrol-decisions-bulk-operations-verify.md | 126 +++++++++++++++++ ...-interface-abstraction-tests-cover-both.md | 113 ++++++++++++++++ ...ontrollers-inject-iauthorizationservice.md | 126 +++++++++++++++++ ...t-sdk-public-apis-build-scripts-declare.md | 121 +++++++++++++++++ ...interop-boundaries-public-ffi-functions.md | 116 ++++++++++++++++ ...actions-authorization-attributes-placed.md | 127 ++++++++++++++++++ ...rations-organization-billing-controller.md | 115 ++++++++++++++++ ...ion-in-rust-sdk-ffi-functions-returning.md | 119 ++++++++++++++++ ...admin-controllers-log-messages-describe.md | 117 ++++++++++++++++ ...zation-authorization-requirements-named.md | 121 +++++++++++++++++ ...copes-authorization-policies-configured.md | 117 ++++++++++++++++ ...ng-support-in-rust-sdk-ffi-entry-points.md | 117 ++++++++++++++++ ...interface-abstraction-tests-verify-that.md | 113 ++++++++++++++++ ...-api-authorization-controllers-use-base.md | 121 +++++++++++++++++ ...ing-strategy-tests-verifying-exceptions.md | 113 ++++++++++++++++ ...ontroller-actions-public-endpoints-that.md | 126 +++++++++++++++++ ...i-endpoints-internal-controller-actions.md | 118 ++++++++++++++++ ...e-integration-services-implement-custom.md | 115 ++++++++++++++++ ...ntegration-tests-tests-use-asserthelper.md | 117 ++++++++++++++++ ...ons-authorization-requirements-enforced.md | 124 +++++++++++++++++ ...on-user-operations-read-only-collection.md | 124 +++++++++++++++++ ...-sdk-cryptographic-operations-involving.md | 114 ++++++++++++++++ ...y-interface-abstraction-tests-use-async.md | 113 ++++++++++++++++ ...s-controllers-use-iauthorizationservice.md | 124 +++++++++++++++++ ...tions-authorization-requirement-classes.md | 126 +++++++++++++++++ ...erface-abstraction-tests-use-dependency.md | 113 ++++++++++++++++ ...vice-failures-return-fallback-responses.md | 117 ++++++++++++++++ ...nagement-in-rust-sdk-ffi-functions-that.md | 114 ++++++++++++++++ ...nterface-abstraction-tests-verify-query.md | 113 ++++++++++++++++ ...ponse-abstraction-integration-tests-use.md | 116 ++++++++++++++++ ...vices-authentication-schemes-configured.md | 121 +++++++++++++++++ ...ring-conversion-ffi-boundary-validation.md | 123 +++++++++++++++++ ...-in-scim-services-test-environments-use.md | 121 +++++++++++++++++ ...uted-cache-cache-implementations-expose.md | 113 ++++++++++++++++ ...net-core-authorization-middleware-added.md | 126 +++++++++++++++++ ...ts-authentication-middleware-registered.md | 125 +++++++++++++++++ ...nd-c-string-conversions-ffi-modules-use.md | 121 +++++++++++++++++ ...-string-conversions-test-suites-include.md | 121 +++++++++++++++++ ...ic-api-contract-cache-configuration-use.md | 113 ++++++++++++++++ ...ntegration-tests-integration-tests-call.md | 113 ++++++++++++++++ ...with-named-scopes-test-environments-use.md | 117 ++++++++++++++++ ...sp-net-core-scim-endpoint-authorization.md | 126 +++++++++++++++++ ...ust-sdk-cryptographic-operations-cipher.md | 117 ++++++++++++++++ ...ion-in-rust-sdk-ffi-functions-returning.md | 122 +++++++++++++++++ ...sting-test-authentication-configuration.md | 102 ++++++++++++++ ...ervice-endpoints-scim-service-endpoints.md | 125 +++++++++++++++++ ...-admin-controllers-log-entries-failures.md | 117 ++++++++++++++++ ...r-rust-sdk-cryptographic-key-generation.md | 121 +++++++++++++++++ ...cstring-conversion-public-ffi-functions.md | 123 +++++++++++++++++ ...vices-authorization-policies-registered.md | 121 +++++++++++++++++ ...sions-custom-authorization-requirements.md | 126 +++++++++++++++++ ...egration-tests-test-factories-configure.md | 113 ++++++++++++++++ ...ributed-cache-redis-connection-failures.md | 113 ++++++++++++++++ ...g-cryptographic-operations-fake-rsa-key.md | 125 +++++++++++++++++ 614 files changed, 47078 insertions(+) create mode 100644 .actual/rules/cross-cutting-additional-authorization-checks-1f05.md create mode 100644 .actual/rules/cross-cutting-additional-cryptographic-key-c744.md create mode 100644 .actual/rules/cross-cutting-additional-diagnostic-context-304d.md create mode 100644 .actual/rules/cross-cutting-additional-fake-keys-c692.md create mode 100644 .actual/rules/cross-cutting-adminconsole-controller-endpoints-9b4c.md create mode 100644 .actual/rules/cross-cutting-authentication-failure-tests-625a.md create mode 100644 .actual/rules/cross-cutting-authentication-handlers-inherit-76ba.md create mode 100644 .actual/rules/cross-cutting-authentication-middleware-registered-f260.md create mode 100644 .actual/rules/cross-cutting-authentication-scheme-configuration-171a.md create mode 100644 .actual/rules/cross-cutting-authentication-schemes-configured-ef9d.md create mode 100644 .actual/rules/cross-cutting-authentication-schemes-registered-a829.md create mode 100644 .actual/rules/cross-cutting-authorization-attributes-applied-9899.md create mode 100644 .actual/rules/cross-cutting-authorization-attributes-placed-9af6.md create mode 100644 .actual/rules/cross-cutting-authorization-attributes-placed-d871.md create mode 100644 .actual/rules/cross-cutting-authorization-attributes-use-9921.md create mode 100644 .actual/rules/cross-cutting-authorization-checks-call-d107.md create mode 100644 .actual/rules/cross-cutting-authorization-checks-execute-2769.md create mode 100644 .actual/rules/cross-cutting-authorization-checks-occur-6a87.md create mode 100644 .actual/rules/cross-cutting-authorization-checks-performed-781f.md create mode 100644 .actual/rules/cross-cutting-authorization-configuration-applied-925c.md create mode 100644 .actual/rules/cross-cutting-authorization-failures-authorizeasync-a3f2.md create mode 100644 .actual/rules/cross-cutting-authorization-failures-throw-5a99.md create mode 100644 .actual/rules/cross-cutting-authorization-failures-throw-7ee9.md create mode 100644 .actual/rules/cross-cutting-authorization-logic-not-ca94.md create mode 100644 .actual/rules/cross-cutting-authorization-middleware-added-7b79.md create mode 100644 .actual/rules/cross-cutting-authorization-middleware-added-f25d.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-combine-b65c.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-configured-4a49.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-configured-dbd8.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-named-4edb.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-registered-94d3.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-registered-b7a3.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-registered-fcbd.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-require-0cb9.md create mode 100644 .actual/rules/cross-cutting-authorization-policies-use-6910.md create mode 100644 .actual/rules/cross-cutting-authorization-requirement-classes-2368.md create mode 100644 .actual/rules/cross-cutting-authorization-requirement-classes-e999.md create mode 100644 .actual/rules/cross-cutting-authorization-requirements-billing-3f88.md create mode 100644 .actual/rules/cross-cutting-authorization-requirements-declared-3c80.md create mode 100644 .actual/rules/cross-cutting-authorization-requirements-enforced-e334.md create mode 100644 .actual/rules/cross-cutting-authorization-requirements-named-db81.md create mode 100644 .actual/rules/cross-cutting-authorization-verification-tests-2daa.md create mode 100644 .actual/rules/cross-cutting-base64-encoding-decoding-0aee.md create mode 100644 .actual/rules/cross-cutting-billing-endpoints-that-b5d9.md create mode 100644 .actual/rules/cross-cutting-boundaries-coordinate-multiple-7266.md create mode 100644 .actual/rules/cross-cutting-build-scripts-declare-d7c8.md create mode 100644 .actual/rules/cross-cutting-bulk-operations-verify-d6b9.md create mode 100644 .actual/rules/cross-cutting-cache-configuration-integrate-4625.md create mode 100644 .actual/rules/cross-cutting-cache-configuration-use-49c3.md create mode 100644 .actual/rules/cross-cutting-cache-configuration-use-f590.md create mode 100644 .actual/rules/cross-cutting-cache-implementations-expose-f10e.md create mode 100644 .actual/rules/cross-cutting-cache-implementations-use-92c0.md create mode 100644 .actual/rules/cross-cutting-cache-registration-encapsulated-b774.md create mode 100644 .actual/rules/cross-cutting-cache-service-registration-1246.md create mode 100644 .actual/rules/cross-cutting-cache-service-registration-175e.md create mode 100644 .actual/rules/cross-cutting-cache-service-registration-2dcf.md create mode 100644 .actual/rules/cross-cutting-cache-service-registration-46f7.md create mode 100644 .actual/rules/cross-cutting-cache-service-registration-b5a1.md create mode 100644 .actual/rules/cross-cutting-collection-access-modifications-3ddb.md create mode 100644 .actual/rules/cross-cutting-context-classes-include-80d4.md create mode 100644 .actual/rules/cross-cutting-controller-action-methods-3351.md create mode 100644 .actual/rules/cross-cutting-controller-action-methods-981f.md create mode 100644 .actual/rules/cross-cutting-controller-actions-not-1aa2.md create mode 100644 .actual/rules/cross-cutting-controller-actions-that-753e.md create mode 100644 .actual/rules/cross-cutting-controllers-apply-authorization-155e.md create mode 100644 .actual/rules/cross-cutting-controllers-apply-custom-0144.md create mode 100644 .actual/rules/cross-cutting-controllers-authorize-attributes-3853.md create mode 100644 .actual/rules/cross-cutting-controllers-bit-adminconsole-60f4.md create mode 100644 .actual/rules/cross-cutting-controllers-bit-billing-446f.md create mode 100644 .actual/rules/cross-cutting-controllers-combine-declarative-1a73.md create mode 100644 .actual/rules/cross-cutting-controllers-combine-multiple-46a6.md create mode 100644 .actual/rules/cross-cutting-controllers-combine-multiple-8f6f.md create mode 100644 .actual/rules/cross-cutting-controllers-handle-aggregate-730e.md create mode 100644 .actual/rules/cross-cutting-controllers-handling-external-8ed8.md create mode 100644 .actual/rules/cross-cutting-controllers-have-class-100f.md create mode 100644 .actual/rules/cross-cutting-controllers-inject-iauthorizationservice-aa26.md create mode 100644 .actual/rules/cross-cutting-controllers-inject-iauthorizationservice-d74b.md create mode 100644 .actual/rules/cross-cutting-controllers-log-operation-b1e7.md create mode 100644 .actual/rules/cross-cutting-controllers-log-successful-0929.md create mode 100644 .actual/rules/cross-cutting-controllers-managing-related-25e3.md create mode 100644 .actual/rules/cross-cutting-controllers-separate-read-1915.md create mode 100644 .actual/rules/cross-cutting-controllers-throw-notfoundexception-cdc8.md create mode 100644 .actual/rules/cross-cutting-controllers-use-allowanonymous-2156.md create mode 100644 .actual/rules/cross-cutting-controllers-use-authorize-1b71.md create mode 100644 .actual/rules/cross-cutting-controllers-use-base-de8d.md create mode 100644 .actual/rules/cross-cutting-controllers-use-iauthorizationservice-e782.md create mode 100644 .actual/rules/cross-cutting-controllers-use-icurrentcontext-7929.md create mode 100644 .actual/rules/cross-cutting-controllers-use-multiple-79e8.md create mode 100644 .actual/rules/cross-cutting-cross-language-data-2955.md create mode 100644 .actual/rules/cross-cutting-cross-language-ffi-ab20.md create mode 100644 .actual/rules/cross-cutting-cryptographic-components-cipher-bbc8.md create mode 100644 .actual/rules/cross-cutting-cryptographic-key-generation-b56a.md create mode 100644 .actual/rules/cross-cutting-cryptographic-key-generation-fbc0.md create mode 100644 .actual/rules/cross-cutting-cryptographic-key-material-893a.md create mode 100644 .actual/rules/cross-cutting-cryptographic-key-types-93ca.md create mode 100644 .actual/rules/cross-cutting-cryptographic-operations-cipher-f6f6.md create mode 100644 .actual/rules/cross-cutting-cryptographic-operations-involving-e4ca.md create mode 100644 .actual/rules/cross-cutting-cryptographic-types-cipher-8303.md create mode 100644 .actual/rules/cross-cutting-csbindgen-configuration-specify-8c53.md create mode 100644 .actual/rules/cross-cutting-cstr-conversions-performed-7c7f.md create mode 100644 .actual/rules/cross-cutting-cstr-string-conversions-205a.md create mode 100644 .actual/rules/cross-cutting-custom-authorization-requirements-7482.md create mode 100644 .actual/rules/cross-cutting-custom-authorization-requirements-789a.md create mode 100644 .actual/rules/cross-cutting-custom-authorization-requirements-fcd6.md create mode 100644 .actual/rules/cross-cutting-custom-result-types-8332.md create mode 100644 .actual/rules/cross-cutting-custom-result-wrappers-23bd.md create mode 100644 .actual/rules/cross-cutting-data-access-operations-1aca.md create mode 100644 .actual/rules/cross-cutting-data-access-operations-44b0.md create mode 100644 .actual/rules/cross-cutting-dbset-properties-organized-86b1.md create mode 100644 .actual/rules/cross-cutting-dbset-property-names-613d.md create mode 100644 .actual/rules/cross-cutting-dedicated-free-string-5122.md create mode 100644 .actual/rules/cross-cutting-distributed-cache-implementations-7a7e.md create mode 100644 .actual/rules/cross-cutting-distributed-caching-implementations-859c.md create mode 100644 .actual/rules/cross-cutting-domain-business-logic-5463.md create mode 100644 .actual/rules/cross-cutting-each-fake-rsa-889f.md create mode 100644 .actual/rules/cross-cutting-each-fake-rsa-9e21.md create mode 100644 .actual/rules/cross-cutting-endpoints-modifying-collection-9595.md create mode 100644 .actual/rules/cross-cutting-endpoints-that-allow-4471.md create mode 100644 .actual/rules/cross-cutting-entity-framework-dbcontext-abc6.md create mode 100644 .actual/rules/cross-cutting-entity-types-requiring-8ef3.md create mode 100644 .actual/rules/cross-cutting-error-log-entries-5cd6.md create mode 100644 .actual/rules/cross-cutting-exception-handling-tests-94de.md create mode 100644 .actual/rules/cross-cutting-exception-logging-within-5e08.md create mode 100644 .actual/rules/cross-cutting-extended-cache-utilities-aaaf.md create mode 100644 .actual/rules/cross-cutting-external-client-calls-7e79.md create mode 100644 .actual/rules/cross-cutting-external-http-client-d376.md create mode 100644 .actual/rules/cross-cutting-external-service-clients-a488.md create mode 100644 .actual/rules/cross-cutting-failed-authorization-checks-d17b.md create mode 100644 .actual/rules/cross-cutting-fake-cryptographic-key-ace5.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-key-229c.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-key-2471.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-key-bfc4.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-key-cbea.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-key-fffb.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-keys-15e4.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-keys-3f21.md create mode 100644 .actual/rules/cross-cutting-fake-rsa-keys-af1e.md create mode 100644 .actual/rules/cross-cutting-ffi-boundary-functions-918a.md create mode 100644 .actual/rules/cross-cutting-ffi-boundary-validation-d076.md create mode 100644 .actual/rules/cross-cutting-ffi-boundary-validation-f057.md create mode 100644 .actual/rules/cross-cutting-ffi-entry-points-dcb8.md create mode 100644 .actual/rules/cross-cutting-ffi-exposed-cryptographic-b670.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-accepting-0ca0.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-accepting-2b77.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-accepting-aff1.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-accepting-bf2a.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-not-5d4a.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-return-7a63.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-return-d4fe.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-returning-07be.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-returning-b569.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-returning-daae.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-returning-f766.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-that-ed1f.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-use-1f6f.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-use-4489.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-use-846b.md create mode 100644 .actual/rules/cross-cutting-ffi-functions-validate-87be.md create mode 100644 .actual/rules/cross-cutting-ffi-modules-document-9333.md create mode 100644 .actual/rules/cross-cutting-ffi-modules-use-10d2.md create mode 100644 .actual/rules/cross-cutting-ffi-modules-use-71f1.md create mode 100644 .actual/rules/cross-cutting-ffi-modules-use-f2ec.md create mode 100644 .actual/rules/cross-cutting-ffi-string-validation-6a74.md create mode 100644 .actual/rules/cross-cutting-ffi-string-validation-d47f.md create mode 100644 .actual/rules/cross-cutting-generated-bindings-specify-95a4.md create mode 100644 .actual/rules/cross-cutting-hardcoded-rsa-private-4685.md create mode 100644 .actual/rules/cross-cutting-http-action-methods-a5bd.md create mode 100644 .actual/rules/cross-cutting-http-client-configurations-b862.md create mode 100644 .actual/rules/cross-cutting-http-clients-registered-2dbc.md create mode 100644 .actual/rules/cross-cutting-http-clients-that-7859.md create mode 100644 .actual/rules/cross-cutting-http-endpoint-methods-6d08.md create mode 100644 .actual/rules/cross-cutting-http-request-headers-a358.md create mode 100644 .actual/rules/cross-cutting-http-requests-scim-d271.md create mode 100644 .actual/rules/cross-cutting-http-response-types-74bf.md create mode 100644 .actual/rules/cross-cutting-implementation-suppress-specific-c43d.md create mode 100644 .actual/rules/cross-cutting-implementations-use-resource-551e.md create mode 100644 .actual/rules/cross-cutting-include-structured-contextual-052d.md create mode 100644 .actual/rules/cross-cutting-infrastructure-services-registered-9d84.md create mode 100644 .actual/rules/cross-cutting-input-validation-ffi-32ec.md create mode 100644 .actual/rules/cross-cutting-integration-test-factories-1764.md create mode 100644 .actual/rules/cross-cutting-integration-test-projects-bc7e.md create mode 100644 .actual/rules/cross-cutting-integration-tests-call-f5ec.md create mode 100644 .actual/rules/cross-cutting-integration-tests-connect-758d.md create mode 100644 .actual/rules/cross-cutting-integration-tests-use-d5ac.md create mode 100644 .actual/rules/cross-cutting-integration-tests-use-ef0e.md create mode 100644 .actual/rules/cross-cutting-internal-controller-actions-e0ea.md create mode 100644 .actual/rules/cross-cutting-json-serialization-use-2eb1.md create mode 100644 .actual/rules/cross-cutting-key-generation-functions-aca2.md create mode 100644 .actual/rules/cross-cutting-key-management-modules-aaf3.md create mode 100644 .actual/rules/cross-cutting-log-entries-failures-fb74.md create mode 100644 .actual/rules/cross-cutting-log-entries-not-bf81.md create mode 100644 .actual/rules/cross-cutting-log-exceptions-external-4360.md create mode 100644 .actual/rules/cross-cutting-log-messages-describe-7507.md create mode 100644 .actual/rules/cross-cutting-log-messages-describe-db43.md create mode 100644 .actual/rules/cross-cutting-logger-verification-use-7680.md create mode 100644 .actual/rules/cross-cutting-logger-verification-use-910f.md create mode 100644 .actual/rules/cross-cutting-logging-statements-use-3a5d.md create mode 100644 .actual/rules/cross-cutting-logging-statements-validation-0931.md create mode 100644 .actual/rules/cross-cutting-memory-allocated-ffi-6520.md create mode 100644 .actual/rules/cross-cutting-modules-containing-fake-c0ec.md create mode 100644 .actual/rules/cross-cutting-multiple-fake-key-4882.md create mode 100644 .actual/rules/cross-cutting-named-authorization-policies-14d3.md create mode 100644 .actual/rules/cross-cutting-named-http-clients-5dbb.md create mode 100644 .actual/rules/cross-cutting-organization-billing-controller-da79.md create mode 100644 .actual/rules/cross-cutting-organization-billing-endpoints-1404.md create mode 100644 .actual/rules/cross-cutting-organization-parameters-billing-b978.md create mode 100644 .actual/rules/cross-cutting-outbound-http-communication-4af2.md create mode 100644 .actual/rules/cross-cutting-production-authorization-policies-0d1f.md create mode 100644 .actual/rules/cross-cutting-production-authorization-policies-a09e.md create mode 100644 .actual/rules/cross-cutting-production-code-paths-c368.md create mode 100644 .actual/rules/cross-cutting-production-scim-policies-3121.md create mode 100644 .actual/rules/cross-cutting-protected-controller-actions-2188.md create mode 100644 .actual/rules/cross-cutting-protected-controller-actions-358e.md create mode 100644 .actual/rules/cross-cutting-protected-controller-endpoints-77bc.md create mode 100644 .actual/rules/cross-cutting-public-endpoints-that-05a5.md create mode 100644 .actual/rules/cross-cutting-public-endpoints-that-46c1.md create mode 100644 .actual/rules/cross-cutting-public-endpoints-that-dff2.md create mode 100644 .actual/rules/cross-cutting-public-ffi-functions-4d31.md create mode 100644 .actual/rules/cross-cutting-public-ffi-functions-d7cf.md create mode 100644 .actual/rules/cross-cutting-public-ffi-functions-fbef.md create mode 100644 .actual/rules/cross-cutting-push-notification-services-09af.md create mode 100644 .actual/rules/cross-cutting-push-notification-services-2769.md create mode 100644 .actual/rules/cross-cutting-read-only-collection-e4b3.md create mode 100644 .actual/rules/cross-cutting-redis-connection-failures-4ea5.md create mode 100644 .actual/rules/cross-cutting-redis-connection-failures-6ee5.md create mode 100644 .actual/rules/cross-cutting-redis-connection-failures-7cfd.md create mode 100644 .actual/rules/cross-cutting-redis-connection-failures-ffdd.md create mode 100644 .actual/rules/cross-cutting-redis-connections-established-6e7b.md create mode 100644 .actual/rules/cross-cutting-restful-http-verbs-5544.md create mode 100644 .actual/rules/cross-cutting-result-types-expose-4249.md create mode 100644 .actual/rules/cross-cutting-result-types-implement-459e.md create mode 100644 .actual/rules/cross-cutting-return-fallback-responses-ecab.md create mode 100644 .actual/rules/cross-cutting-rsa-key-operations-065c.md create mode 100644 .actual/rules/cross-cutting-rust-sdk-modules-4738.md create mode 100644 .actual/rules/cross-cutting-scim-endpoint-authorization-f6bd.md create mode 100644 .actual/rules/cross-cutting-scim-endpoint-tests-3944.md create mode 100644 .actual/rules/cross-cutting-scim-integration-tests-c5f8.md create mode 100644 .actual/rules/cross-cutting-scim-named-policy-cbc1.md create mode 100644 .actual/rules/cross-cutting-scim-service-endpoints-f9a4.md create mode 100644 .actual/rules/cross-cutting-scope-based-authorization-bd9c.md create mode 100644 .actual/rules/cross-cutting-self-modification-operations-9860.md create mode 100644 .actual/rules/cross-cutting-self-modification-operations-b5aa.md create mode 100644 .actual/rules/cross-cutting-service-controllers-separate-385f.md create mode 100644 .actual/rules/cross-cutting-service-registration-occur-aab5.md create mode 100644 .actual/rules/cross-cutting-services-extend-base-95a6.md create mode 100644 .actual/rules/cross-cutting-services-implement-custom-e177.md create mode 100644 .actual/rules/cross-cutting-services-processing-notifications-c775.md create mode 100644 .actual/rules/cross-cutting-services-register-multiple-1cc0.md create mode 100644 .actual/rules/cross-cutting-shared-cryptographic-resources-16aa.md create mode 100644 .actual/rules/cross-cutting-string-data-crossing-3353.md create mode 100644 .actual/rules/cross-cutting-string-validation-failures-12ca.md create mode 100644 .actual/rules/cross-cutting-swagger-openapi-document-b183.md create mode 100644 .actual/rules/cross-cutting-test-authentication-configuration-f8dc.md create mode 100644 .actual/rules/cross-cutting-test-authentication-handlers-98aa.md create mode 100644 .actual/rules/cross-cutting-test-authentication-handlers-9daa.md create mode 100644 .actual/rules/cross-cutting-test-authentication-handlers-9e7c.md create mode 100644 .actual/rules/cross-cutting-test-authentication-handlers-c778.md create mode 100644 .actual/rules/cross-cutting-test-authentication-handlers-d009.md create mode 100644 .actual/rules/cross-cutting-test-authentication-schemes-58ef.md create mode 100644 .actual/rules/cross-cutting-test-authentication-schemes-ba44.md create mode 100644 .actual/rules/cross-cutting-test-authorization-policies-9816.md create mode 100644 .actual/rules/cross-cutting-test-claims-include-d13f.md create mode 100644 .actual/rules/cross-cutting-test-code-define-c095.md create mode 100644 .actual/rules/cross-cutting-test-code-exercising-1293.md create mode 100644 .actual/rules/cross-cutting-test-code-requiring-7fee.md create mode 100644 .actual/rules/cross-cutting-test-code-use-30b7.md create mode 100644 .actual/rules/cross-cutting-test-environments-configure-a1e8.md create mode 100644 .actual/rules/cross-cutting-test-environments-define-bd63.md create mode 100644 .actual/rules/cross-cutting-test-environments-register-a385.md create mode 100644 .actual/rules/cross-cutting-test-environments-use-9167.md create mode 100644 .actual/rules/cross-cutting-test-environments-use-bc29.md create mode 100644 .actual/rules/cross-cutting-test-environments-use-f094.md create mode 100644 .actual/rules/cross-cutting-test-environments-use-f608.md create mode 100644 .actual/rules/cross-cutting-test-factories-configure-fdb2.md create mode 100644 .actual/rules/cross-cutting-test-factories-use-7687.md create mode 100644 .actual/rules/cross-cutting-test-fixture-setup-79b4.md create mode 100644 .actual/rules/cross-cutting-test-fixtures-cryptographic-562a.md create mode 100644 .actual/rules/cross-cutting-test-fixtures-requiring-be91.md create mode 100644 .actual/rules/cross-cutting-test-fixtures-use-2eaa.md create mode 100644 .actual/rules/cross-cutting-test-helpers-report-03d0.md create mode 100644 .actual/rules/cross-cutting-test-methods-that-9dfa.md create mode 100644 .actual/rules/cross-cutting-test-servers-inject-716f.md create mode 100644 .actual/rules/cross-cutting-test-suites-include-f3f0.md create mode 100644 .actual/rules/cross-cutting-test-suites-requiring-a086.md create mode 100644 .actual/rules/cross-cutting-tests-append-custom-9f5d.md create mode 100644 .actual/rules/cross-cutting-tests-assert-jsonvaluekind-54d7.md create mode 100644 .actual/rules/cross-cutting-tests-cover-both-d730.md create mode 100644 .actual/rules/cross-cutting-tests-use-asserthelper-e296.md create mode 100644 .actual/rules/cross-cutting-tests-use-async-e659.md create mode 100644 .actual/rules/cross-cutting-tests-use-dependency-eab0.md create mode 100644 .actual/rules/cross-cutting-tests-use-linq-ad5d.md create mode 100644 .actual/rules/cross-cutting-tests-use-received-b50c.md create mode 100644 .actual/rules/cross-cutting-tests-validate-operation-8bf3.md create mode 100644 .actual/rules/cross-cutting-tests-validating-successful-1a26.md create mode 100644 .actual/rules/cross-cutting-tests-verify-asynchronous-557f.md create mode 100644 .actual/rules/cross-cutting-tests-verify-number-61b8.md create mode 100644 .actual/rules/cross-cutting-tests-verify-query-eeeb.md create mode 100644 .actual/rules/cross-cutting-tests-verify-specific-0346.md create mode 100644 .actual/rules/cross-cutting-tests-verify-that-de1c.md create mode 100644 .actual/rules/cross-cutting-tests-verifying-exceptions-de9f.md create mode 100644 .actual/rules/cross-cutting-typed-requirement-classes-b695.md create mode 100644 .actual/rules/cross-cutting-unit-tests-query-8f98.md create mode 100644 .actual/rules/cross-cutting-unit-tests-use-bee1.md create mode 100644 .actual/rules/cross-cutting-unit-tests-verify-d040.md create mode 100644 .actual/rules/cross-cutting-use-logerror-level-2e07.md create mode 100644 .actual/rules/cross-cutting-wrap-external-service-ce6b.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 docs/adr/0144da07-6cd7-45ba-9cd7-f0584aa34ead-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-apply-custom.md create mode 100644 docs/adr/03460212-4b7e-492f-8a14-fa879008634d-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-specific.md create mode 100644 docs/adr/03d051fd-23a0-4eb5-b917-18767dc87480-enforce-authorization-attributes-on-api-controllers-via-unit-tests-test-helpers-report.md create mode 100644 docs/adr/052d6875-cc91-4f25-b7be-7a8e5370916f-use-structured-logging-with-contextual-parameters-for-external-service-failures-include-structured-contextual.md create mode 100644 docs/adr/05a53096-c159-4325-aee5-9c6a1acd88df-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-public-endpoints-that.md create mode 100644 docs/adr/065cedd3-19a8-40d8-a11f-e45077be274a-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-rsa-key-operations.md create mode 100644 docs/adr/07bef05b-46f9-49a1-8146-08515ab97e21-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-returning.md create mode 100644 docs/adr/0929cc83-dbde-4cc8-823b-acab2af6ef9e-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-log-successful.md create mode 100644 docs/adr/0931104c-fe38-4781-b9f7-a75a7a4e7450-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-logging-statements-validation.md create mode 100644 docs/adr/09afc0f6-e646-46ab-b05d-69adb04ccfd7-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md create mode 100644 docs/adr/0aeea845-ad1a-44d3-a49f-f78e57388421-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-base64-encoding-decoding.md create mode 100644 docs/adr/0ca06cfe-e64d-42d3-b847-78554bc2595f-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-accepting.md create mode 100644 docs/adr/0cb98c9c-8648-4035-b801-527526b20ada-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authorization-policies-require.md create mode 100644 docs/adr/0d1f5b18-b490-49be-8e39-8faaa1e2424f-standardize-authorization-policy-configuration-with-named-scopes-production-authorization-policies.md create mode 100644 docs/adr/100f3767-af9d-45f5-885f-9a4456ace179-enforce-authorization-attributes-on-api-controllers-via-unit-tests-controllers-have-class.md create mode 100644 docs/adr/10d29bf0-d5fa-475e-9947-741b253d41f4-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-modules-use.md create mode 100644 docs/adr/1246ffac-4184-4102-bae0-11c0852aef3d-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md create mode 100644 docs/adr/129355f1-5bef-4966-8db2-3b85d084cd4c-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-code-exercising.md create mode 100644 docs/adr/12ca8d34-55df-4dd0-accb-6f82613bb8d6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-string-validation-failures.md create mode 100644 docs/adr/1404fbba-3345-4129-a549-1e89fd72a4fa-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-endpoints.md create mode 100644 docs/adr/14d355fa-4151-47ec-be57-af33dec27278-standardize-authorization-policy-configuration-with-named-scopes-named-authorization-policies.md create mode 100644 docs/adr/155e3926-1c5d-48a3-bd0f-17d5c45398f1-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-apply-authorization.md create mode 100644 docs/adr/15e40d0d-ad1f-48d7-93c8-4a2a34a133b1-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md create mode 100644 docs/adr/16aa9187-10a7-4726-9b4c-ec41d1641aaa-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-shared-cryptographic-resources.md create mode 100644 docs/adr/171a2ff9-448e-44ad-aea6-5b5acdfde617-standardize-authorization-policy-configuration-with-named-scopes-authentication-scheme-configuration.md create mode 100644 docs/adr/175e5898-be14-42bf-af34-1bbf3b90ece2-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md create mode 100644 docs/adr/17646b12-9b44-429d-8cda-26504ef06142-adopt-api-key-authentication-scheme-for-scim-service-endpoints-integration-test-factories.md create mode 100644 docs/adr/19153cc8-fd17-4cdd-b627-3b7a111b4fe4-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-separate-read.md create mode 100644 docs/adr/1a263ad8-362a-4bed-8d4c-ff152c9ea4f0-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-validating-successful.md create mode 100644 docs/adr/1a73e7c0-65d3-440c-b1eb-3c8d3997c31f-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-combine-declarative.md create mode 100644 docs/adr/1aa263f5-bb5a-4c72-9391-5470aed03a1c-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controller-actions-not.md create mode 100644 docs/adr/1acafa6d-8d2f-49da-8c36-0b8c136c602f-use-system-text-json-for-scim-api-data-access-serialization-data-access-operations.md create mode 100644 docs/adr/1b71f2d5-afd2-4ba4-8a75-16c87a1823dc-adopt-attribute-based-authorization-model-for-controller-actions-controllers-use-authorize.md create mode 100644 docs/adr/1cc0b477-2d8d-47e4-a0b8-8cc86275aaf1-establish-http-client-boundaries-for-external-service-integration-services-register-multiple.md create mode 100644 docs/adr/1f053f1e-a6ad-4c43-a3dc-e069331b9ca5-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-additional-authorization-checks.md create mode 100644 docs/adr/1f6f7f84-717f-498e-b845-592fe052e6d8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-functions-use.md create mode 100644 docs/adr/205a829c-f4e2-45ae-9b0a-5ccbb7494a9b-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-cstr-string-conversions.md create mode 100644 docs/adr/2156771a-e379-4878-b99f-176aad22109b-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-use-allowanonymous.md create mode 100644 docs/adr/218891f7-9da8-4417-a739-5140c3f11a36-enforce-authorization-service-pattern-for-access-control-decisions-protected-controller-actions.md create mode 100644 docs/adr/229cd360-3e71-4202-a291-9c178aaed87e-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md create mode 100644 docs/adr/2368cf82-a8ac-4c40-a698-2eb3e6e5c486-adopt-attribute-based-authorization-model-for-controller-actions-authorization-requirement-classes.md create mode 100644 docs/adr/23bdf879-b4fe-4d4a-bdde-45ddc7890b0b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-wrappers.md create mode 100644 docs/adr/2471eb0e-c976-49b7-9c1b-8d163631e101-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md create mode 100644 docs/adr/25e3448a-34bf-4fa3-bbdb-5cfa75a9a738-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controllers-managing-related.md create mode 100644 docs/adr/27694fe9-9e4c-49dc-9467-1a147b3a864e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md create mode 100644 docs/adr/27695c88-64e9-48cb-94cb-0759a0ba7b96-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-checks-execute.md create mode 100644 docs/adr/29556473-2e70-4ba2-aea9-40b4dd4a120c-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-cross-language-data.md create mode 100644 docs/adr/2b775808-03a5-4387-84e4-0cb3a0b2162a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md create mode 100644 docs/adr/2daa6496-ac17-4ea7-a429-ab8b08960dc9-enforce-authorization-attributes-on-api-controllers-via-unit-tests-authorization-verification-tests.md create mode 100644 docs/adr/2dbcdbcc-a1f8-4732-afa0-68852b3eec23-adopt-http-client-abstraction-for-external-service-integration-http-clients-registered.md create mode 100644 docs/adr/2dcfc033-1bdc-4e09-9c4f-fd7199b9e904-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md create mode 100644 docs/adr/2e078989-f0a0-4944-b666-6028a7c74890-use-structured-logging-with-contextual-parameters-for-external-service-failures-use-logerror-level.md create mode 100644 docs/adr/2eaa7b00-5d0f-40bf-b471-3a0993ccac0e-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-test-fixtures-use.md create mode 100644 docs/adr/2eb105ee-ef02-4462-9a0f-7284bb1c2b10-use-system-text-json-for-scim-api-data-access-serialization-json-serialization-use.md create mode 100644 docs/adr/304d2cd5-6451-4c86-a8c1-c6eca4bbcdc7-log-redis-connection-failures-in-distributed-cache-extensions-additional-diagnostic-context.md create mode 100644 docs/adr/30b72ec9-4f3f-4f1c-8352-06631ef7b00f-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-use.md create mode 100644 docs/adr/3121bce3-ebbb-40ed-92ef-7b413ac61c13-enforce-authorization-via-policy-based-configuration-in-scim-services-production-scim-policies.md create mode 100644 docs/adr/32ec4bdf-3e54-40c5-924a-208e17fbd125-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-input-validation-ffi.md create mode 100644 docs/adr/3351ba53-1850-4f4d-ad66-4c82146e896a-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md create mode 100644 docs/adr/335364a7-51cc-460c-94b0-ceb75ebe48f8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-string-data-crossing.md create mode 100644 docs/adr/358e360f-ab17-4202-b212-3da0c0c3dc5d-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-protected-controller-actions.md create mode 100644 docs/adr/38530c47-f864-481a-9c77-d612e8841263-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-authorize-attributes.md create mode 100644 docs/adr/385fbeac-2009-4964-97f0-f639567e8c51-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-service-controllers-separate.md create mode 100644 docs/adr/39443d4c-df3a-4eb5-87de-4a7f1c7d774a-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-scim-endpoint-tests.md create mode 100644 docs/adr/3a5da651-71a4-4609-ac03-ac704880f5b9-log-redis-connection-failures-in-distributed-cache-extensions-logging-statements-use.md create mode 100644 docs/adr/3c805701-1aa6-4179-a7ab-df1380c5fa57-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-requirements-declared.md create mode 100644 docs/adr/3ddbdebe-6c15-4864-b8f9-d988d0954a44-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-collection-access-modifications.md create mode 100644 docs/adr/3f212963-2a7a-4edd-83a7-6faf9f37b6b4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md create mode 100644 docs/adr/3f888895-b046-4f11-bc2d-3b22882e76b0-enforce-organization-scoped-authorization-requirements-for-billing-operations-authorization-requirements-billing.md create mode 100644 docs/adr/4249ecc3-367a-40f2-99f8-b23616365041-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-expose.md create mode 100644 docs/adr/4360e829-692d-4f6c-9197-2e9deaa4506e-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-exceptions-external.md create mode 100644 docs/adr/446f3d19-4bdb-4bd7-aa9f-d1e9a2c73445-enforce-organization-scoped-authorization-requirements-for-billing-operations-controllers-bit-billing.md create mode 100644 docs/adr/447141c6-c7e6-48b8-9ea6-daefae21dc4b-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-endpoints-that-allow.md create mode 100644 docs/adr/44897d9c-1b04-4264-9ce1-6b1a6b4094d8-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-use.md create mode 100644 docs/adr/44b0e5cd-7f0f-4a32-8d94-965b081e74cf-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-data-access-operations.md create mode 100644 docs/adr/459ea228-d332-4b52-a7a4-490be0ffde40-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-implement.md create mode 100644 docs/adr/46259ca9-c088-47b1-b31a-417242ff61a0-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-integrate.md create mode 100644 docs/adr/46855cf7-686a-4e5e-9502-81b84d5cf9c5-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-hardcoded-rsa-private.md create mode 100644 docs/adr/46a677e4-20f6-494b-a3a7-01251f967dbb-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-combine-multiple.md create mode 100644 docs/adr/46c10ab6-e5e1-43e2-9c32-a4ae1256f5db-adopt-attribute-based-authorization-model-for-controller-actions-public-endpoints-that.md create mode 100644 docs/adr/46f70fba-6b32-4984-a7f2-97fc8f124e81-log-redis-connection-failures-in-distributed-cache-extensions-cache-service-registration.md create mode 100644 docs/adr/4738e6e5-da0f-4f81-8170-17e1787a2708-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-rust-sdk-modules.md create mode 100644 docs/adr/4882b808-5c7b-4443-b150-5b4d9e5492ec-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-multiple-fake-key.md create mode 100644 docs/adr/49c3eb8d-cc66-4014-b066-2f29f3d823ee-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-configuration-use.md create mode 100644 docs/adr/4a4909d9-8d78-44fe-9b7e-a3dbe089be24-enforce-authorization-service-pattern-for-access-control-decisions-authorization-policies-configured.md create mode 100644 docs/adr/4af296a2-06e6-4fea-abfc-0a806e7df47f-adopt-http-client-abstraction-for-external-service-integration-outbound-http-communication.md create mode 100644 docs/adr/4d319375-586c-4c89-974a-cf57f147755c-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-public-ffi-functions.md create mode 100644 docs/adr/4ea57ab2-43b0-4e07-8de2-6d07829a71c8-expose-extended-cache-configuration-as-public-api-contract-redis-connection-failures.md create mode 100644 docs/adr/4edbda29-90a0-4c8a-97b6-e7a0bb5e58dd-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-named.md create mode 100644 docs/adr/51226e02-a611-40b7-9343-4e32cd7697ba-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-dedicated-free-string.md create mode 100644 docs/adr/54636413-d057-4d7a-a8d4-19e29618dc76-enforce-authorization-via-policy-based-configuration-in-scim-services-domain-business-logic.md create mode 100644 docs/adr/54d7258e-000f-4f7d-8079-9c820d805cdd-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-assert-jsonvaluekind.md create mode 100644 docs/adr/551e5ab9-76a3-4125-9ac8-ad71f0e4f1f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-implementations-use-resource.md create mode 100644 docs/adr/5544cf8d-e169-4f44-87c2-4fbb865f009f-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-restful-http-verbs.md create mode 100644 docs/adr/557fb6ef-5a71-4648-9beb-9a4d6f0504c2-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verify-asynchronous.md create mode 100644 docs/adr/562a1fb2-8e5c-4ec8-9b46-1106e26df9fe-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-test-fixtures-cryptographic.md create mode 100644 docs/adr/58ef2725-e19b-493e-9a95-7b5c168213cf-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-schemes.md create mode 100644 docs/adr/5a99a8f6-738b-4a0c-8d4b-af692c7977fb-enforce-authorization-service-pattern-for-access-control-decisions-authorization-failures-throw.md create mode 100644 docs/adr/5cd6ec70-a27a-44ff-a08f-ccf37d7b0e93-log-redis-connection-failures-in-distributed-cache-extensions-error-log-entries.md create mode 100644 docs/adr/5d4a8535-38ea-4839-8a6d-38029726ae65-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-not.md create mode 100644 docs/adr/5dbb6704-3c65-4f9a-b03b-68cf4c7f95b9-establish-http-client-boundaries-for-external-service-integration-named-http-clients.md create mode 100644 docs/adr/5e080c9b-be10-4cf4-aa70-fe5e5d4cf4a3-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-exception-logging-within.md create mode 100644 docs/adr/60f4f273-53c2-4a31-b733-f88485f7d07b-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-bit-adminconsole.md create mode 100644 docs/adr/613d377b-9885-4202-8c35-5dc7040c6b9b-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-property-names.md create mode 100644 docs/adr/61b87c11-8189-45b9-bdb0-07a0b193e382-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-number.md create mode 100644 docs/adr/625af6eb-2999-45fa-865d-97ab13837d42-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-authentication-failure-tests.md create mode 100644 docs/adr/652092c8-86ba-4e27-a202-23567b7338de-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-memory-allocated-ffi.md create mode 100644 docs/adr/69102dad-97f7-491e-88fe-9133675beb97-register-core-infrastructure-services-via-dependency-injection-container-authorization-policies-use.md create mode 100644 docs/adr/6a74e276-66db-449a-929c-65a5f57ce685-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md create mode 100644 docs/adr/6a8737dc-387f-416a-afe6-4d35b3083143-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-checks-occur.md create mode 100644 docs/adr/6d08223f-13b7-41cc-87df-78b85c3f2721-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-http-endpoint-methods.md create mode 100644 docs/adr/6e7b7016-eb84-47d3-8a29-a78cd5f8e5b4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connections-established.md create mode 100644 docs/adr/6ee5e5c9-4eba-4aa1-a0c7-c45396eddc9f-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connection-failures.md create mode 100644 docs/adr/716f591a-8197-4b3a-9b4e-8289d3220344-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-servers-inject.md create mode 100644 docs/adr/71f1e1e1-3305-40ed-8ef5-c8334377ee96-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-modules-use.md create mode 100644 docs/adr/72668b21-de9e-48dc-a3e4-390f41bff7b5-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-boundaries-coordinate-multiple.md create mode 100644 docs/adr/730eeb26-7617-47a6-ac66-d0b722c94a7c-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-handle-aggregate.md create mode 100644 docs/adr/74822a96-3248-4fde-b4ba-fae354caf724-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-custom-authorization-requirements.md create mode 100644 docs/adr/74bf715a-53ae-4c13-be5f-a29c89c0478b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-http-response-types.md create mode 100644 docs/adr/7507ed7f-d610-4f43-853a-2f85cc6254d9-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-messages-describe.md create mode 100644 docs/adr/753e6ac5-2d04-49b3-9c29-48bf5ef452fb-adopt-attribute-based-authorization-model-for-controller-actions-controller-actions-that.md create mode 100644 docs/adr/758dcc20-8b27-421a-a3a3-d27e3e2f5d57-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-connect.md create mode 100644 docs/adr/76807d1e-075a-4dfb-8034-4d3ce093ebe1-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md create mode 100644 docs/adr/76873ea9-7582-4103-8bba-d3a38075aac8-use-system-text-json-for-scim-api-data-access-serialization-test-factories-use.md create mode 100644 docs/adr/76ba54b2-0ca8-4aca-b2e1-b8c4cce7f095-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-handlers-inherit.md create mode 100644 docs/adr/77bc5fcb-f89e-4ff6-abb4-4d1494ae4c74-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-protected-controller-endpoints.md create mode 100644 docs/adr/781f6b28-4c7f-4deb-817d-762221188c8c-enforce-authorization-service-pattern-for-access-control-decisions-authorization-checks-performed.md create mode 100644 docs/adr/78593eda-af88-4bd6-9784-a3e7ccb7e150-establish-http-client-boundaries-for-external-service-integration-http-clients-that.md create mode 100644 docs/adr/789a3481-a7e9-43af-aac1-53564623b268-adopt-attribute-based-authorization-model-for-controller-actions-custom-authorization-requirements.md create mode 100644 docs/adr/79299188-39e7-484d-b952-b1e8cb4262cc-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-use-icurrentcontext.md create mode 100644 docs/adr/79b476ff-5365-46ea-b2b7-01b630ab12c9-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-fixture-setup.md create mode 100644 docs/adr/79e85707-b8a9-497c-9cdc-d3444434f00d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-use-multiple.md create mode 100644 docs/adr/7a63602c-8f91-4721-82e4-587068e3f75f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-return.md create mode 100644 docs/adr/7a7eb6e8-901b-416d-980b-f0a6b1158259-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-distributed-cache-implementations.md create mode 100644 docs/adr/7b79a03b-7943-44f6-b8a1-5dbcc0ece8b8-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-middleware-added.md create mode 100644 docs/adr/7c7fbe23-7f8f-4fdd-afdc-b01aa29eac8e-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-cstr-conversions-performed.md create mode 100644 docs/adr/7cfd3bd7-4395-4876-b379-f8b4e676c501-log-redis-connection-failures-in-distributed-cache-extensions-redis-connection-failures.md create mode 100644 docs/adr/7e79fd2f-f710-4f04-9d12-f46135302205-establish-http-client-boundaries-for-external-service-integration-external-client-calls.md create mode 100644 docs/adr/7ee91a40-96b5-4068-9cbc-bfa50d5641ac-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-failures-throw.md create mode 100644 docs/adr/7fee142b-06b9-432b-81ec-911cb732b053-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-requiring.md create mode 100644 docs/adr/80d4fa0c-c256-4ad8-be81-9dd26277d7de-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-context-classes-include.md create mode 100644 docs/adr/8303fcd7-1b32-4ea7-a6c0-a42d3079eac9-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-types-cipher.md create mode 100644 docs/adr/8332d4f6-d878-4891-85f3-f261cf790c5f-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-types.md create mode 100644 docs/adr/846bc329-4589-4607-9efd-6033c355563a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-use.md create mode 100644 docs/adr/859c13ba-4abb-4b8d-85ce-aac9e8f13ed5-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-distributed-caching-implementations.md create mode 100644 docs/adr/86b1ddae-ffa0-4f45-8f93-0ab9ec630cc8-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-properties-organized.md create mode 100644 docs/adr/87be164b-bd95-43a3-ae40-6f0fa34ced4a-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-validate.md create mode 100644 docs/adr/889fa803-9d10-47fd-8fa5-96a0dd4899e7-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-each-fake-rsa.md create mode 100644 docs/adr/893a7c18-91d2-4ec7-b446-5ad2251fa57d-validate-ffi-input-using-rust-type-system-and-c-string-conversions-cryptographic-key-material.md create mode 100644 docs/adr/8bf3971d-2183-4106-bb02-1d737379e42a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-validate-operation.md create mode 100644 docs/adr/8c53f1bd-3055-4879-a45c-7be3e98c1a96-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-csbindgen-configuration-specify.md create mode 100644 docs/adr/8ed82d97-4d70-4553-988f-f79331b9ef22-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-handling-external.md create mode 100644 docs/adr/8ef3fe32-3e55-45e5-9b27-56d1ca7de403-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-types-requiring.md create mode 100644 docs/adr/8f6f9141-ac0c-48f6-8d5e-02b7e6a25e43-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-combine-multiple.md create mode 100644 docs/adr/8f9885e8-0c25-422f-9a77-cf407a73f7b0-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-unit-tests-query.md create mode 100644 docs/adr/910fe798-7802-4a1e-9329-07007b1ea997-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md create mode 100644 docs/adr/916751b2-b271-443c-9795-004adff9f00b-enforce-authorization-service-pattern-for-access-control-decisions-test-environments-use.md create mode 100644 docs/adr/918af20b-0276-447f-88f2-b10ecc4f55a9-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-boundary-functions.md create mode 100644 docs/adr/925c710e-4e51-42f8-8fc3-06b61c142cdd-standardize-authorization-policy-configuration-with-named-scopes-authorization-configuration-applied.md create mode 100644 docs/adr/92c03b28-7ea3-46c3-aa8f-b89cb67bcb9b-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-implementations-use.md create mode 100644 docs/adr/93330207-06c0-4452-9a7a-8d3d66685272-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-modules-document.md create mode 100644 docs/adr/93ca6910-d73c-400a-9049-65abe6c60978-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-key-types.md create mode 100644 docs/adr/94d3fff7-cc0a-47a0-bd13-0d957a5de9fb-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-policies-registered.md create mode 100644 docs/adr/94de471a-d3c3-4311-9187-13e91cebe0f2-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-exception-handling-tests.md create mode 100644 docs/adr/9595cb10-0420-4f1a-8b54-84969f09ad4d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-endpoints-modifying-collection.md create mode 100644 docs/adr/95a40c26-775a-4a73-b44e-6fc159188177-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-generated-bindings-specify.md create mode 100644 docs/adr/95a61a86-bb62-4b1a-8d77-320971142c14-expose-extended-cache-configuration-as-public-api-contract-services-extend-base.md create mode 100644 docs/adr/98164f52-434e-46c9-af87-18909877ff3f-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-authorization-policies.md create mode 100644 docs/adr/981f8aa3-70d1-4704-b00a-242fa78bbfa2-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md create mode 100644 docs/adr/9860d08f-ad1a-48b1-8d99-3c3dfff6f9c7-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-self-modification-operations.md create mode 100644 docs/adr/9899c5f7-96f5-47d3-824a-880f38e2b5ff-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-authorization-attributes-applied.md create mode 100644 docs/adr/98aaa6a5-b1a5-4074-a5ba-5538ff2f5170-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md create mode 100644 docs/adr/992104d8-afad-416b-b1a2-d79762911a30-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-attributes-use.md create mode 100644 docs/adr/9af66387-57a0-4867-861d-db50c047a087-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-attributes-placed.md create mode 100644 docs/adr/9b4c7f7c-92f0-4916-9cd1-03d66a263b7e-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-adminconsole-controller-endpoints.md create mode 100644 docs/adr/9d841473-59fe-4b92-a6a2-5a70f8f090b4-register-core-infrastructure-services-via-dependency-injection-container-infrastructure-services-registered.md create mode 100644 docs/adr/9daa4246-124f-4135-8383-599b5cb24aba-use-system-text-json-for-scim-api-data-access-serialization-test-authentication-handlers.md create mode 100644 docs/adr/9dfa9d4e-39bb-4768-b815-2b42f885a25f-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-methods-that.md create mode 100644 docs/adr/9e21df4f-bead-4cac-b324-68e089a7ab17-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-each-fake-rsa.md create mode 100644 docs/adr/9e7ca0aa-4dab-4df2-bc68-8b163f841d29-register-core-infrastructure-services-via-dependency-injection-container-test-authentication-handlers.md create mode 100644 docs/adr/9f5d3eea-eccf-4e82-aef9-dbc13844e4ae-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-tests-append-custom.md create mode 100644 docs/adr/a0860e4d-6381-47ea-b146-63016a984641-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-suites-requiring.md create mode 100644 docs/adr/a09e8e4e-72c4-4cdf-9532-4356d0da43a2-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-production-authorization-policies.md create mode 100644 docs/adr/a1e870a0-0dc1-4fe8-a9cf-2fac8e888b6e-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-test-environments-configure.md create mode 100644 docs/adr/a358d52b-a70b-42c1-b2aa-03d2f8fae6e1-establish-http-client-boundaries-for-external-service-integration-http-request-headers.md create mode 100644 docs/adr/a3851f8b-cb87-4a32-b0f2-afcdd5864124-register-core-infrastructure-services-via-dependency-injection-container-test-environments-register.md create mode 100644 docs/adr/a3f292d1-1cab-4f76-991e-4a83fba87e42-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-failures-authorizeasync.md create mode 100644 docs/adr/a4882536-e976-4b5b-b9c4-76184baf709d-adopt-http-client-abstraction-for-external-service-integration-external-service-clients.md create mode 100644 docs/adr/a5bdfb20-cb01-4912-b128-8694d29c60b6-enforce-authorization-attributes-on-api-controllers-via-unit-tests-http-action-methods.md create mode 100644 docs/adr/a82901b9-0179-442c-841a-6b741dd1b9f5-register-core-infrastructure-services-via-dependency-injection-container-authentication-schemes-registered.md create mode 100644 docs/adr/aa269035-dd58-4901-be93-7ced95cd3b0c-enforce-authorization-service-pattern-for-access-control-decisions-controllers-inject-iauthorizationservice.md create mode 100644 docs/adr/aaaf4b07-0f57-4370-94a8-edfd8a440f2c-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-extended-cache-utilities.md create mode 100644 docs/adr/aab5279c-67a4-460e-827a-dedceac4a97e-register-core-infrastructure-services-via-dependency-injection-container-service-registration-occur.md create mode 100644 docs/adr/aaf34ea5-54c3-43cc-a210-03bf483dedb2-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-management-modules.md create mode 100644 docs/adr/ab20330d-42a3-40d9-954b-b5fb1aaeff15-adopt-http-client-abstraction-for-external-service-integration-cross-language-ffi.md create mode 100644 docs/adr/abc628f2-d591-45bf-8221-4b8a79fe0b5a-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-framework-dbcontext.md create mode 100644 docs/adr/aca2792a-f5da-41d3-91ed-f225a11fc94c-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-generation-functions.md create mode 100644 docs/adr/ace52160-226e-413e-80cd-682f2d78db99-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-fake-cryptographic-key.md create mode 100644 docs/adr/ad5d08c9-8728-47e5-b261-fa5e075ee348-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-linq.md create mode 100644 docs/adr/af1e829e-bf47-40d9-bc3a-c282b0a91de4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md create mode 100644 docs/adr/aff187d4-e8a6-49ef-9f8a-0a6f86b4d48f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-accepting.md create mode 100644 docs/adr/b18395c7-d0da-4b8c-8091-bb4e2da35352-enforce-authorization-attributes-on-api-controllers-via-unit-tests-swagger-openapi-document.md create mode 100644 docs/adr/b1e7db38-2432-46ef-944c-12699fc054f2-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-log-operation.md create mode 100644 docs/adr/b50c1537-803a-4460-8c5d-49b40744ec96-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-received.md create mode 100644 docs/adr/b569cad3-d31f-4e1c-b491-858e64c8d8bf-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-returning.md create mode 100644 docs/adr/b56acf9d-5917-4557-8014-57020819af23-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-key-generation.md create mode 100644 docs/adr/b5a143c2-0481-4e32-8cb8-cfafca5ce423-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md create mode 100644 docs/adr/b5aa68ab-f345-4b09-b35f-327118015892-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-self-modification-operations.md create mode 100644 docs/adr/b5d99c3b-d0d8-4d81-bcde-af3fcc76ee3f-enforce-organization-scoped-authorization-requirements-for-billing-operations-billing-endpoints-that.md create mode 100644 docs/adr/b65c1be4-a418-4582-bdb0-f734ba86efc4-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-combine.md create mode 100644 docs/adr/b6700091-00ec-4e70-84f3-648c1a9bb652-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-ffi-exposed-cryptographic.md create mode 100644 docs/adr/b69528d8-c594-445d-b5fb-9410756a89c7-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-typed-requirement-classes.md create mode 100644 docs/adr/b774d498-b072-4740-8391-71e62deb6dd4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-registration-encapsulated.md create mode 100644 docs/adr/b7a378ff-2230-4630-bcae-4b368ef2174f-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-registered.md create mode 100644 docs/adr/b862eccf-5190-4192-b73e-c7cee246b8c3-adopt-http-client-abstraction-for-external-service-integration-http-client-configurations.md create mode 100644 docs/adr/b97877a2-3da0-42cb-812b-54c702b80a92-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-parameters-billing.md create mode 100644 docs/adr/ba44ca4f-2765-4398-b3c4-113ea2bab4dd-adopt-test-authentication-scheme-for-integration-testing-test-authentication-schemes.md create mode 100644 docs/adr/bbc83d26-64c4-4e7c-a505-7a9b2665a645-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-components-cipher.md create mode 100644 docs/adr/bc29ebf0-457a-4663-9f3e-02531612373e-establish-http-client-boundaries-for-external-service-integration-test-environments-use.md create mode 100644 docs/adr/bc7e164b-099b-4ba0-8e7e-c50e8ff13166-adopt-test-authentication-scheme-for-integration-testing-integration-test-projects.md create mode 100644 docs/adr/bd635931-0c61-4030-8a96-afebe0b1149c-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-test-environments-define.md create mode 100644 docs/adr/bd9c0591-a386-4d5e-a80d-763893e0e961-standardize-authorization-policy-configuration-with-named-scopes-scope-based-authorization.md create mode 100644 docs/adr/be91c795-209c-4756-a476-c7299c3bd4f9-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-fixtures-requiring.md create mode 100644 docs/adr/bee1ce59-2afa-4c78-a877-66249177f453-enforce-authorization-attributes-on-api-controllers-via-unit-tests-unit-tests-use.md create mode 100644 docs/adr/bf2ab4ec-7f8d-492a-b356-25c2f0b9eac4-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md create mode 100644 docs/adr/bf81a88a-0c42-4cb9-b420-079805d48869-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-not.md create mode 100644 docs/adr/bfc4a3c9-a71f-4235-8343-7602daa8576c-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md create mode 100644 docs/adr/c0954ece-5f93-4c49-acaf-337ccb671903-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-test-code-define.md create mode 100644 docs/adr/c0eccdcc-f9f8-4371-85bc-935d747950f8-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-modules-containing-fake.md create mode 100644 docs/adr/c368c23f-80fd-4b43-8ae5-2c4f9d2cb067-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-production-code-paths.md create mode 100644 docs/adr/c43d4ce1-3b5f-4e6d-8f9b-8a57664a6f36-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-implementation-suppress-specific.md create mode 100644 docs/adr/c5f8d2c9-7e8d-44e2-8502-2f67bf280239-use-system-text-json-for-scim-api-data-access-serialization-scim-integration-tests.md create mode 100644 docs/adr/c6925c30-52cd-4b6a-b3a6-106604368441-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-additional-fake-keys.md create mode 100644 docs/adr/c74440d5-44bb-41b7-9a51-afde8974ce39-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-additional-cryptographic-key.md create mode 100644 docs/adr/c775e1b6-3ca1-4da9-88d0-761fad4b473e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-services-processing-notifications.md create mode 100644 docs/adr/c7780231-7bef-4325-9208-971b925b454d-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md create mode 100644 docs/adr/ca94f258-8ca7-4c19-aad5-3ba8b6328c0f-adopt-attribute-based-authorization-model-for-controller-actions-authorization-logic-not.md create mode 100644 docs/adr/cbc17a37-2cd6-4449-a1ae-9d42f7dc45f5-enforce-authorization-via-policy-based-configuration-in-scim-services-scim-named-policy.md create mode 100644 docs/adr/cbeaee5b-97cf-4120-9994-da5d9621a7df-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md create mode 100644 docs/adr/cdc85dc0-fd41-44d2-a677-7ccca2beebe1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-throw-notfoundexception.md create mode 100644 docs/adr/ce6b97e8-0b9b-45b4-bc6f-c2adb5a24a9c-use-structured-logging-with-contextual-parameters-for-external-service-failures-wrap-external-service.md create mode 100644 docs/adr/d009f0b4-3905-4624-80b9-2ca46f364016-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-handlers.md create mode 100644 docs/adr/d0407e8f-b352-48a5-b1a6-53fdb423ddc1-verify-logger-invocations-in-unit-tests-for-observability-components-unit-tests-verify.md create mode 100644 docs/adr/d0768299-875b-48c7-8762-179423ce299e-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-boundary-validation.md create mode 100644 docs/adr/d1075a6d-f799-4490-b756-78ce09ef24d0-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-checks-call.md create mode 100644 docs/adr/d13fb5ff-b73e-4677-8d19-7ae186771c89-adopt-test-authentication-scheme-for-integration-testing-test-claims-include.md create mode 100644 docs/adr/d17b61a0-9737-4968-b771-1210d7cfb5a1-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-failed-authorization-checks.md create mode 100644 docs/adr/d2712e9d-1ee5-4a6a-be5b-b080bbbc34e6-use-system-text-json-for-scim-api-data-access-serialization-http-requests-scim.md create mode 100644 docs/adr/d376f581-9ece-4f04-a0b9-d56ac4fa12bb-establish-http-client-boundaries-for-external-service-integration-external-http-client.md create mode 100644 docs/adr/d47f7772-dcb8-4c92-a949-c0a8fef043ad-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md create mode 100644 docs/adr/d4fedf70-1502-4676-a146-a2f18eee1340-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-return.md create mode 100644 docs/adr/d5ace3d3-7f05-4d88-bfe2-cc82cf13a7e3-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-use.md create mode 100644 docs/adr/d6b99429-7694-4bb1-831c-eeb84b33654c-enforce-authorization-service-pattern-for-access-control-decisions-bulk-operations-verify.md create mode 100644 docs/adr/d7303975-2017-4fe8-90bb-4a566464eef6-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-cover-both.md create mode 100644 docs/adr/d74bb1a6-73ee-4c6e-bdbb-ad4d548547b1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-inject-iauthorizationservice.md create mode 100644 docs/adr/d7c80df6-2821-40b1-896c-773d22cd3543-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-build-scripts-declare.md create mode 100644 docs/adr/d7cf8560-2b44-4465-8754-102fecae7236-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-public-ffi-functions.md create mode 100644 docs/adr/d87126b1-1707-44e1-a967-b3ed03510e7c-adopt-attribute-based-authorization-model-for-controller-actions-authorization-attributes-placed.md create mode 100644 docs/adr/da790b60-15b3-4bf4-9937-0fe3f9aadba9-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-controller.md create mode 100644 docs/adr/daae2af9-369d-4fcc-b20a-d10c0f1d03f6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md create mode 100644 docs/adr/db430582-fad9-41d5-92df-f2d3f63b417b-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-messages-describe.md create mode 100644 docs/adr/db813764-d050-4876-94d4-0e28cba2b6e0-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-requirements-named.md create mode 100644 docs/adr/dbd8aab1-ab4a-4f5a-8ffb-becc2a19bfa1-standardize-authorization-policy-configuration-with-named-scopes-authorization-policies-configured.md create mode 100644 docs/adr/dcb80ee8-6360-45cd-b6b0-608633a0450d-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-ffi-entry-points.md create mode 100644 docs/adr/de1c22f9-d8ba-4eca-bb3e-ea5d64b8e226-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-that.md create mode 100644 docs/adr/de8d2acb-b47a-439b-a60e-efe4b11cee60-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-controllers-use-base.md create mode 100644 docs/adr/de9f504d-885a-43ed-b247-3dfd6643354a-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verifying-exceptions.md create mode 100644 docs/adr/dff2c838-b9c1-4a48-8adb-8c612733d23b-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-public-endpoints-that.md create mode 100644 docs/adr/e0ea0450-c5af-4e11-a0b5-871bc1543346-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-internal-controller-actions.md create mode 100644 docs/adr/e1776714-355e-4af4-8981-ebbc0835371b-adopt-http-client-abstraction-for-external-service-integration-services-implement-custom.md create mode 100644 docs/adr/e296cb7f-ba9f-4ae7-9961-70276b3c544a-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-use-asserthelper.md create mode 100644 docs/adr/e334b687-3e75-4f83-9416-0376bf123735-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-requirements-enforced.md create mode 100644 docs/adr/e4b39357-d928-4adb-b122-794be886cc4b-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-read-only-collection.md create mode 100644 docs/adr/e4cab412-0466-4df2-9c64-80bb2e9e897c-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-operations-involving.md create mode 100644 docs/adr/e6596a48-53e0-4b58-9297-172d935261dd-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-async.md create mode 100644 docs/adr/e782046c-a190-4db5-9ebc-3191004e3b34-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-controllers-use-iauthorizationservice.md create mode 100644 docs/adr/e99923c1-abac-4b79-8b4a-16a0918ab5f9-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-requirement-classes.md create mode 100644 docs/adr/eab0181a-1b33-4cfc-bfab-97f8aaf0ef10-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-dependency.md create mode 100644 docs/adr/ecab59e9-ab15-4328-a38c-6ebe589b784d-use-structured-logging-with-contextual-parameters-for-external-service-failures-return-fallback-responses.md create mode 100644 docs/adr/ed1f3bfd-e75f-4a51-b083-1e9ff6c63c3f-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-functions-that.md create mode 100644 docs/adr/eeeb0b67-297d-4d5d-be90-ca0ff7011f0a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-query.md create mode 100644 docs/adr/ef0e6a8b-31a8-4d14-8127-dda7d12de886-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-integration-tests-use.md create mode 100644 docs/adr/ef9da943-1527-4e31-a94f-b20de8163e9c-enforce-authorization-via-policy-based-configuration-in-scim-services-authentication-schemes-configured.md create mode 100644 docs/adr/f0570cf5-0f1d-4069-81c2-d602ba323070-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-boundary-validation.md create mode 100644 docs/adr/f0941089-2e5d-43c2-8f5a-52162d5a565e-enforce-authorization-via-policy-based-configuration-in-scim-services-test-environments-use.md create mode 100644 docs/adr/f10e50f9-1793-4078-bf2c-f87b82a11333-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-implementations-expose.md create mode 100644 docs/adr/f25d68ac-56d9-4222-93c1-b739d5abcf7e-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-middleware-added.md create mode 100644 docs/adr/f2603862-ba99-4ae7-bc7e-0252d4ad11ab-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-middleware-registered.md create mode 100644 docs/adr/f2ec3be2-47e8-4626-9d21-f6a29049c4f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-modules-use.md create mode 100644 docs/adr/f3f0b5bc-743a-4b38-b3c9-7f1376973b7a-validate-ffi-input-using-rust-type-system-and-c-string-conversions-test-suites-include.md create mode 100644 docs/adr/f59075ec-7f34-4421-9572-193d3c9ee869-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-use.md create mode 100644 docs/adr/f5ec24ef-0f13-4808-a252-ebb15c6726e0-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-integration-tests-call.md create mode 100644 docs/adr/f608c3ab-b657-400c-b7e6-9bea9ad78794-standardize-authorization-policy-configuration-with-named-scopes-test-environments-use.md create mode 100644 docs/adr/f6bde425-ff4b-4ba8-9610-7c913f3a12ec-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-scim-endpoint-authorization.md create mode 100644 docs/adr/f6f6d796-e5f5-455e-9ee0-463991270cce-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-operations-cipher.md create mode 100644 docs/adr/f766c552-4097-49a8-ab9c-efc885073a79-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md create mode 100644 docs/adr/f8dc926d-f900-4ef3-aae4-f2117e32e004-adopt-test-authentication-scheme-for-integration-testing-test-authentication-configuration.md create mode 100644 docs/adr/f9a4858e-ea4a-426c-bb8e-6fc3a10fb197-adopt-api-key-authentication-scheme-for-scim-service-endpoints-scim-service-endpoints.md create mode 100644 docs/adr/fb740243-8248-4287-971c-36a708d8c36a-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-failures.md create mode 100644 docs/adr/fbc0365b-bba7-4bc2-b4bb-0667cfe7b8d6-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-key-generation.md create mode 100644 docs/adr/fbefe97a-b42f-4765-86e9-e0fa40079305-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-public-ffi-functions.md create mode 100644 docs/adr/fcbd71ee-73d7-435c-983b-76fc42f54448-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-policies-registered.md create mode 100644 docs/adr/fcd63002-33ef-4693-9995-de547f45589e-enforce-authorization-service-pattern-for-access-control-decisions-custom-authorization-requirements.md create mode 100644 docs/adr/fdb27347-e3f0-49f2-a5db-da80b3eab9d3-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-factories-configure.md create mode 100644 docs/adr/ffddbcb9-7c00-4a51-a626-c52702ef8e99-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-redis-connection-failures.md create mode 100644 docs/adr/fffb6c6b-569b-4502-bfd8-77134aa02e25-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md diff --git a/.actual/rules/cross-cutting-additional-authorization-checks-1f05.md b/.actual/rules/cross-cutting-additional-authorization-checks-1f05.md new file mode 100644 index 000000000000..b04bc67c7b80 --- /dev/null +++ b/.actual/rules/cross-cutting-additional-authorization-checks-1f05.md @@ -0,0 +1,30 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Additional Authorization Checks + +These rules are ALWAYS ACTIVE for all API controller endpoints requiring authorization in the AdminConsole API surface, specifically all controllers in the Bit.Api.AdminConsole.Controllers namespace handling authenticated requests. + +### Rules + +- **R-AUTHZ-001** MAY: Additional authorization checks using ICurrentContext MAY be performed within endpoint methods for complex authorization logic that cannot be expressed declaratively. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async Task methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either `[Authorize]` or `[AllowAnonymous]` attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based `Authorize(Policy = "...")` attributes for authorization requirements +- Complex authorization logic split between declarative attributes and imperative ICurrentContext checks is documented with clear rationale + + +Claude Code MUST NOT skip or defer verification. All controller methods must be audited for proper authorization attribute application. Violations must be flagged during code review and CI pipeline checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-additional-cryptographic-key-c744.md b/.actual/rules/cross-cutting-additional-cryptographic-key-c744.md new file mode 100644 index 000000000000..f2363f9fe161 --- /dev/null +++ b/.actual/rules/cross-cutting-additional-cryptographic-key-c744.md @@ -0,0 +1,38 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Additional Cryptographic Key + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions exposed through C FFI boundaries in the Rust SDK, including all functions in `util/RustSdk/rust/src/lib.rs` that allocate or manipulate cryptographic material across language boundaries. + +### Rules + +- **R-FFI-CRYPTO-001** MAY: Additional cryptographic key generation functions MAY be added following the established FFI-safe pattern with paired allocation/deallocation. +- **R-FFI-CRYPTO-002** MUST: All new FFI functions that allocate memory must provide a corresponding `free_*` function and document the caller's responsibility to invoke it. +- **R-FFI-CRYPTO-003** MUST: Use `std::panic::catch_unwind` around `CString` conversions to prevent panics from crossing FFI boundaries, returning error codes instead. +- **R-FFI-CRYPTO-004** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-FFI-CRYPTO-005** SHOULD: Maintain test mocks for cipher and rsa_keys components that cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns. +- **R-FFI-CRYPTO-006** SHOULD: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production. + +### Verify + +```bash +# Verify all public FFI functions for key generation use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in the public API for memory deallocation +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used for FFI boundary operations +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use `c_char` pointers with `CString`/`CStr` conversions +- A `free_c_string` function exists in the public API for memory deallocation +- `std::ffi` types are imported and used for FFI boundary operations +- All FFI functions that allocate memory have paired deallocation functions +- `CString` conversions include error handling via `std::panic::catch_unwind` or equivalent +- Input validation is performed at FFI boundaries before passing to cryptographic functions +- Test infrastructure includes mocks for cipher and rsa_keys components with edge case coverage + + +Claude Code MUST NOT skip or defer verification. Code review of all FFI boundary functions must verify paired allocation/deallocation. Static analysis must detect `CString` conversions without corresponding error handling. Memory leak detection in CI using valgrind or similar tools on FFI integration tests is mandatory. FFI functions without paired deallocation functions must be rejected in code review. Memory leaks detected in CI must block merge until resolved. Panics at FFI boundaries must be converted to error returns before production deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-additional-diagnostic-context-304d.md b/.actual/rules/cross-cutting-additional-diagnostic-context-304d.md new file mode 100644 index 000000000000..27c441633fe8 --- /dev/null +++ b/.actual/rules/cross-cutting-additional-diagnostic-context-304d.md @@ -0,0 +1,36 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Additional Diagnostic Context + +These rules are ALWAYS ACTIVE for all cache service registration extensions and distributed cache initialization code that uses StackExchangeRedis or ConnectionMultiplexer.Connect operations. + +### Rules + +- **R-REDIS-001** MUST: Wrap all ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions. +- **R-REDIS-002** MUST: Log connection failures using ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: `logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName)`. +- **R-REDIS-003** MUST: Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns. +- **R-REDIS-004** MAY: Include additional diagnostic context such as connection string (sanitized) or retry attempts in error logs. +- **R-REDIS-005** SHOULD: Consider adding correlation IDs or request context to error logs for distributed tracing integration. +- **R-REDIS-006** MUST: Sanitize connection strings before logging to avoid credential leakage in logs. + +### Verify + +```bash +# Verify Redis connection error logging is present +grep -r 'LogError.*Failed to connect to Redis' src/ + +# Count ConnectionMultiplexer.Connect calls wrapped with try-catch +grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' + +# Run cache initialization tests with detailed logging +dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters +- Connection strings are sanitized and do not contain credentials in log output +- ILogger instances are properly injected and configured before cache service registration + + +Claude Code MUST NOT skip or defer verification. All Redis connection initialization code MUST include error logging with structured context. Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks are treated as build failures in CI pipeline. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-additional-fake-keys-c692.md b/.actual/rules/cross-cutting-additional-fake-keys-c692.md new file mode 100644 index 000000000000..2801a431b631 --- /dev/null +++ b/.actual/rules/cross-cutting-additional-fake-keys-c692.md @@ -0,0 +1,49 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Additional Fake Keys + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop test suites. + +### Rules + +- **R-FAKE-RSA-001** MAY: Additional fake keys beyond the initial set MAY be added following the sequential naming convention (_FAKE_RSA_KEY_5, _FAKE_RSA_KEY_6, etc.) as test scenarios require. + +- **R-FAKE-RSA-002** MUST: All fake RSA keys MUST be embedded as const string literals containing full PEM-encoded 2048-bit RSA private keys in the test fixtures module (e.g., src/test_fixtures/rsa_keys.rs). + +- **R-FAKE-RSA-003** MUST: Fake RSA keys MUST NEVER appear in production source files, production code paths, or non-test modules; static analysis MUST verify this constraint. + +- **R-FAKE-RSA-004** MUST: Each fake key constant MUST include a comment header explicitly stating it is a test fixture and must never be used in production. + +- **R-FAKE-RSA-005** SHOULD: Fake keys SHOULD use zero-indexed sequential naming (_FAKE_RSA_KEY_0, _FAKE_RSA_KEY_1, etc.) with documented purpose if representing specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing). + +- **R-FAKE-RSA-006** MUST: All test code using RSA operations MUST reference _FAKE_RSA_KEY_N constants from the standardized test fixtures module. + +- **R-FAKE-RSA-007** MUST: C# test code consuming the Rust SDK via csbindgen MUST use identical fake key material as Rust tests, either by copying keys to a C# test fixture class or by calling Rust test helper functions that return the fake keys. + +- **R-FAKE-RSA-008** MUST: At least 5 distinct fake RSA keys MUST be available in the test fixtures module to support multi-party protocols, key rotation simulation, and edge case testing. + +### Verify + +```bash +# Verify no fake keys appear in production code (outside test modules) +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify minimum 5 fake keys exist +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +# Verify fake key naming convention +grep '_FAKE_RSA_KEY_[0-9]' util/RustSdk/rust/src/rsa_keys.rs | wc -l | awk '$1 >= 5 {print "Naming convention verified"}' +``` + +**Accept when:** +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Static analysis confirms no _FAKE_RSA_KEY_ patterns exist outside test modules +- Each fake key constant includes a comment header identifying it as a test fixture + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting this rule as satisfied. Static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules MUST pass in CI. Code review MUST verify that cryptographic tests use standardized fake keys and follow the naming convention. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-adminconsole-controller-endpoints-9b4c.md b/.actual/rules/cross-cutting-adminconsole-controller-endpoints-9b4c.md new file mode 100644 index 000000000000..bc1a065ca37c --- /dev/null +++ b/.actual/rules/cross-cutting-adminconsole-controller-endpoints-9b4c.md @@ -0,0 +1,40 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Adminconsole Controller Endpoints + +These rules are ALWAYS ACTIVE for all API controller endpoints requiring authorization in the AdminConsole API surface, specifically all controllers in the Bit.Api.AdminConsole.Controllers namespace and HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests. + +### Rules + +- **R-ADMINCONSOLE-001** MUST: All AdminConsole API controller endpoints that require authorization MUST use the generic `Authorize` attribute with a typed requirement class. +- **R-ADMINCONSOLE-002** MUST: All authorization requirement classes MUST be defined in `Bit.Api.AdminConsole.Authorization` namespace or subnamespaces and follow the `Requirement` naming suffix convention (e.g., `ManageUsersRequirement`, `ManagePoliciesRequirement`). +- **R-ADMINCONSOLE-003** MUST: Controller methods MUST NOT use string-based `Authorize(Policy = "...")` attributes for authorization requirements. +- **R-ADMINCONSOLE-004** MUST: Public endpoints explicitly marked with `AllowAnonymous` MUST be documented to indicate intentional bypass of authorization. +- **R-ADMINCONSOLE-005** SHOULD: Apply `[Authorize("Application")]` at the controller class level to enforce base authentication, then apply `[Authorize]` at the method level for specific authorization requirements. +- **R-ADMINCONSOLE-006** SHOULD: For endpoints requiring multiple authorization checks, combine declarative `Authorize` attributes with imperative `ICurrentContext` checks, documenting the rationale for imperative checks. +- **R-ADMINCONSOLE-007** MAY: Endpoints that validate tokens or provide pre-authentication information (e.g., `GetByToken` in `PoliciesController`) are excepted from this rule (EXC-001). +- **R-ADMINCONSOLE-008** MAY: Deprecated endpoints maintaining backward compatibility (e.g., `PostDelete` methods) are excepted from this rule (EXC-002). + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes defined in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +# Check for string-based Authorize(Policy = "...") usage +grep -r "Authorize(Policy" src/Api/AdminConsole/Controllers/ | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either `[Authorize]` or `[AllowAnonymous]` attributes +- All requirement classes are defined in `Bit.Api.AdminConsole.Authorization` namespace or subnamespaces and follow the `Requirement` naming suffix convention +- No controller methods use string-based `Authorize(Policy = "...")` attributes for authorization requirements +- Public endpoints explicitly marked with `AllowAnonymous` are documented with security rationale + + +Claude Code MUST NOT skip or defer verification. All new or modified AdminConsole controller endpoints MUST be verified against these rules before approval. Static analysis during CI pipeline MUST fail if controller methods lack proper authorization attributes. Code review MUST block merge until authorization attributes are properly applied. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-failure-tests-625a.md b/.actual/rules/cross-cutting-authentication-failure-tests-625a.md new file mode 100644 index 000000000000..11997075da35 --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-failure-tests-625a.md @@ -0,0 +1,37 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Authentication Failure Tests + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses, including password grant, SSO authorization code flow, and trusted device encryption scenarios. + +### Rules + +- **R-AUTH-FAIL-001** MUST: Authentication failure tests MUST validate specific error message content using Assert.Equal with expected error strings (e.g., 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device'). +- **R-AUTH-FAIL-002** MUST: Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access. +- **R-AUTH-FAIL-003** MUST: Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods. +- **R-AUTH-FAIL-004** MUST: Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information). +- **R-AUTH-FAIL-005** SHOULD: For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties. + +### Verify + +```bash +# Check for System.Text.Json usage in integration tests +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Check for Assert.Equal error message validation patterns +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run integration tests for OAuth token endpoint validation +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + + +Claude Code MUST NOT skip or defer verification. Code review of integration test pull requests MUST check for System.Text.Json usage and JsonValueKind assertions. CI pipeline execution of Identity.IntegrationTest suite MUST validate test pass rates. Pull requests introducing integration tests without proper JSON validation patterns MUST be flagged in code review. Test failures due to missing or incorrect JSON assertions MUST block merge until corrected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-handlers-inherit-76ba.md b/.actual/rules/cross-cutting-authentication-handlers-inherit-76ba.md new file mode 100644 index 000000000000..8bf1a3d2892f --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-handlers-inherit-76ba.md @@ -0,0 +1,43 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authentication Handlers Inherit + +These rules are ALWAYS ACTIVE for all SCIM service authentication handler implementations in the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces, including Startup.cs authentication configuration, ApiKeyAuthenticationHandler, ApiKeyAuthenticationOptions, and test authentication handlers. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Authentication handlers MUST inherit from AuthenticationHandler and implement HandleAuthenticateAsync to return AuthenticateResult with ClaimsPrincipal. +- **R-SCIM-AUTH-002** MUST: All SCIM service Startup.cs files MUST register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme. +- **R-SCIM-AUTH-003** MUST: Authorization policies named 'Scim' MUST require authenticated users and enforce 'api.scim' scope claims. +- **R-SCIM-AUTH-004** MUST: Authentication middleware MUST be registered before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization(). +- **R-SCIM-AUTH-005** MUST: ApiKeyAuthenticationHandler MUST validate API keys against secure storage and populate ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-AUTH-006** MUST: Test authentication handlers MUST be implemented in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-AUTH-007** MUST: Test authentication handlers MUST inherit from AuthenticationHandler with proper claims population. +- **R-SCIM-AUTH-008** SHOULD: Authentication tickets SHOULD include organizational context claims (e.g., 'orgadmin' with organization ID) to support multi-tenant authorization logic. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy configuration +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers inherit from AuthenticationHandler +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- ApiKeyAuthenticationHandler validates API keys and populates ClaimsPrincipal with scope claims +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline +- Test authentication handlers use clear naming conventions and are not present in production code paths + + +Claude Code MUST NOT skip or defer verification. All rules R-SCIM-AUTH-001 through R-SCIM-AUTH-008 are mandatory for SCIM authentication implementations. Violations require security review and remediation before merge. Pull requests modifying authentication configuration without maintaining the prescribed pattern are blocked. Production deployments with test authentication handlers registered trigger automated rollback and incident response. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-middleware-registered-f260.md b/.actual/rules/cross-cutting-authentication-middleware-registered-f260.md new file mode 100644 index 000000000000..a2510ad1ad46 --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-middleware-registered-f260.md @@ -0,0 +1,39 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authentication Middleware Registered + +These rules are ALWAYS ACTIVE for all SCIM service endpoints under `/v2/{organizationId}/groups` and `/v2/{organizationId}/users` routes, ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations, authorization policies named 'Scim' with scope-based claim requirements, integration test authentication handlers, and ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods within the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD: Authentication middleware SHOULD be registered before authorization middleware in the ASP.NET Core pipeline using UseAuthentication followed by UseAuthorization. +- **R-SCIM-AUTH-002** MUST: ApiKeyAuthenticationHandler MUST validate API keys against secure storage and populate ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-AUTH-003** MUST: Authorization policies named 'Scim' MUST require authenticated users and enforce 'api.scim' scope claims. +- **R-SCIM-AUTH-004** MUST: Test authentication handlers MUST be implemented in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-AUTH-005** SHOULD: Organizational context claims (e.g., 'orgadmin' with organization ID) SHOULD be included in authentication tickets to support multi-tenant authorization logic. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy configuration +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers are isolated +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline +- ApiKeyAuthenticationHandler properly validates credentials and populates scope claims + + +Clause Code MUST NOT skip or defer verification. Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review. Production deployments with test authentication handlers registered trigger automated rollback and incident response. Authorization policy changes that weaken scope claim requirements require security team approval. Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-scheme-configuration-171a.md b/.actual/rules/cross-cutting-authentication-scheme-configuration-171a.md new file mode 100644 index 000000000000..00b0a19dc0cb --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-scheme-configuration-171a.md @@ -0,0 +1,31 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authentication Scheme Configuration + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTH-001** MUST: Authentication scheme configuration MUST precede authorization policy configuration in the service registration pipeline. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- AddAuthentication is called before AddAuthorization in all service registration pipelines +- Policy names are defined as constants in shared configuration classes and referenced consistently + + +Claude Code MUST NOT skip or defer verification. Static code analysis scanning for authorization policy configurations in CI/CD pipeline is mandatory. Security-focused code review checklist verification is required. Automated integration tests validating authorization behavior with valid and invalid tokens must pass. CI/CD pipeline MUST fail builds containing permissive authorization policies in production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-schemes-configured-ef9d.md b/.actual/rules/cross-cutting-authentication-schemes-configured-ef9d.md new file mode 100644 index 000000000000..3febaf039664 --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-schemes-configured-ef9d.md @@ -0,0 +1,37 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authentication Schemes Configured + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including all SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes, services implementing IScimContext and ICurrentContext interfaces, controllers decorated with authorization policy attributes, and middleware pipeline components between UseAuthentication and UseAuthorization. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Authentication schemes MUST be configured before authorization policies are defined. +- **R-SCIM-AUTH-002** MUST: All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy. +- **R-SCIM-AUTH-003** MUST: Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope. +- **R-SCIM-AUTH-004** MUST: Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods. +- **R-SCIM-AUTH-005** MUST: app.UseAuthentication() must be placed before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation. +- **R-SCIM-AUTH-006** SHOULD: Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity. +- **R-SCIM-AUTH-007** SHOULD: Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments. + +### Verify + +```bash +# Verify AddAuthorization configuration with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify RequireClaim for api.scim scope +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- app.UseAuthentication() is positioned before app.UseAuthorization() in all Configure methods +- Named policies ('Scim') are used consistently across startup configuration and controller authorization attributes + + +Claude Code MUST NOT skip or defer verification. All rules marked MUST are mandatory and must be verified before accepting code changes. Violations result in pull request blocks and require security team review for any exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authentication-schemes-registered-a829.md b/.actual/rules/cross-cutting-authentication-schemes-registered-a829.md new file mode 100644 index 000000000000..df4daf2e5bf6 --- /dev/null +++ b/.actual/rules/cross-cutting-authentication-schemes-registered-a829.md @@ -0,0 +1,29 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Authentication Schemes Registered + +These rules are ALWAYS ACTIVE for all files in the application that configure dependency injection, authentication, authorization, or service registration patterns, particularly in factory classes, startup configurations, and integration test infrastructure. + +### Rules + +- **R-AUTH-001** MUST: Authentication schemes MUST be registered via AddAuthentication with explicit scheme names before configuring authorization policies. + +### Verify + +```bash +# Verify dependency injection patterns are in active use +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration is present +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Verify test factory classes exist with service collection configuration +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + + +Claude Code MUST NOT skip or defer verification. Authentication schemes MUST be registered before authorization policies are configured. Service registration patterns MUST use dependency injection container methods (AddSingleton, AddScoped, AddTransient) rather than direct instantiation or service locator patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-attributes-applied-9899.md b/.actual/rules/cross-cutting-authorization-attributes-applied-9899.md new file mode 100644 index 000000000000..e7a51c45e2b9 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-attributes-applied-9899.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Authorization Attributes Applied + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces where authorization requirements must be declared via attributes on controller actions. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization attributes MUST be applied at the method level to make per-endpoint authorization requirements explicit and auditable. +- **R-AUTHZ-002** MUST: All controller action methods in AdminConsole and Admin namespaces MUST have either `[Authorize]` or `[AllowAnonymous]` attributes. +- **R-AUTHZ-003** MUST: Custom authorization requirement types MUST be defined in dedicated Authorization namespaces (e.g., `Bit.Api.AdminConsole.Authorization.Requirements`). +- **R-AUTHZ-004** MUST: Each custom requirement type MUST have a corresponding `IAuthorizationHandler` implementation registered in the dependency injection container. +- **R-AUTHZ-005** SHOULD: Requirement type names SHOULD be descriptive and clearly communicate the authorization intent (e.g., `ManageUsersRequirement`, `ProviderAdminRequirement`). +- **R-AUTHZ-006** SHOULD: Endpoints that intentionally allow anonymous access SHOULD explicitly apply `[AllowAnonymous]` to document the decision. +- **R-AUTHZ-007** MAY: Complex authorization scenarios requiring multiple contextual checks MAY implement imperative authorization checks via `IAuthorizationService.AuthorizeAsync()` only when declarative attributes cannot express the requirement, with documented exception. + +### Verify + +```bash +# Scan for controller actions without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization namespace imports +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either `[Authorize]` or `[AllowAnonymous]` attributes +- No controller action methods contain imperative authorization checks (`IAuthorizationService.AuthorizeAsync` calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI +- All new controller actions include appropriate authorization attributes or documented exceptions +- Authorization requirement types use descriptive names that clearly communicate intent + + +Claude Code MUST NOT skip or defer verification. All controller actions must be scanned for missing authorization attributes. Violations must be flagged and exceptions must be explicitly documented with security review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-attributes-placed-9af6.md b/.actual/rules/cross-cutting-authorization-attributes-placed-9af6.md new file mode 100644 index 000000000000..b4fa6267de27 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-attributes-placed-9af6.md @@ -0,0 +1,30 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Authorization Attributes Placed + +These rules are ALWAYS ACTIVE for all API controller endpoints in the Bit.Api.AdminConsole namespace requiring authorization. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization attributes MUST be placed on individual HTTP verb methods (HttpGet, HttpPost, HttpPut, HttpDelete) rather than at the controller class level when requirements vary by endpoint. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async Task methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes defined in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements +- Endpoints marked with exceptions (EXC-001: token validation endpoints; EXC-002: deprecated backward-compatibility methods) are documented in code comments + + +Claude Code MUST NOT skip or defer verification. Static analysis during CI pipeline using custom Roslyn analyzers or linting rules is mandatory. Code review must verify authorization attributes on all new endpoints. Security team conducts quarterly audits of authorization patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-attributes-placed-d871.md b/.actual/rules/cross-cutting-authorization-attributes-placed-d871.md new file mode 100644 index 000000000000..4de7ed6a7cc6 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-attributes-placed-d871.md @@ -0,0 +1,36 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Attributes Placed + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects, specifically HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization attributes MUST be placed on individual action methods rather than controller classes when different actions require different permissions. +- **R-AUTHZ-002** MUST: All controller action methods returning IResult or IActionResult MUST have either [Authorize], [Authorize], or [AllowAnonymous] attributes. +- **R-AUTHZ-003** MUST: Custom authorization requirement classes MUST implement IAuthorizationRequirement and have corresponding registered handler implementations. +- **R-AUTHZ-004** MUST: All [AllowAnonymous] usage MUST be documented with security rationale in code comments and justified in pull request descriptions. +- **R-AUTHZ-005** SHOULD: Authorization handler implementations SHOULD include unit tests achieving >90% code coverage with both positive authorization and denial test cases. +- **R-AUTHZ-006** SHOULD: Complex authorization requirements SHOULD use composite requirement types for common permission combinations rather than attribute proliferation. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All [AllowAnonymous] endpoints are documented with security rationale and approved by security team + + +Claude Code MUST NOT skip or defer verification. Static analysis rules in CI pipeline MUST detect controller actions without authorization attributes. Pull requests MUST be blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-attributes-use-9921.md b/.actual/rules/cross-cutting-authorization-attributes-use-9921.md new file mode 100644 index 000000000000..3da2cbaa423c --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-attributes-use-9921.md @@ -0,0 +1,29 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Authorization Attributes Use + +These rules are ALWAYS ACTIVE for all internal API endpoint implementations requiring authorization enforcement, specifically all controller actions in Bit.Api.AdminConsole.Controllers and Bit.Admin.Controllers namespaces managing organization resources or requiring authenticated access. + +### Rules + +- **R-AUTH-001** SHOULD: Authorization attributes SHOULD use typed requirement classes (e.g., ManageUsersRequirement) that implement IAuthorizationRequirement to enable testable and reusable authorization policies. + +### Verify + +```bash +# Count authorization attributes on internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Verify public action methods have authorization attributes +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific unit tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + + +Claude Code MUST NOT skip or defer verification. All internal API endpoints must have authorization attributes applied before code is considered compliant with this rule. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-checks-call-d107.md b/.actual/rules/cross-cutting-authorization-checks-call-d107.md new file mode 100644 index 000000000000..49e1e2c142f9 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-checks-call-d107.md @@ -0,0 +1,34 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Authorization Checks Call + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, and service configuration in Startup or Program.cs registering authorization policies. + +### Rules + +- **R-AUTH-001** MUST: Authorization checks MUST call AuthorizeAsync with the current User principal, the resource being accessed, and the specific authorization requirement or operation. + +### Verify + +```bash +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers (excluding comments) +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization is registered in service configuration +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count custom authorization handlers +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- Authorization failures throw NotFoundException to prevent information disclosure + + +Claude Code MUST NOT skip or defer verification of authorization checks. All protected endpoints MUST be verified to call AuthorizeAsync with appropriate resource context and requirements. Missing authorization checks are treated as critical security defects. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-checks-execute-2769.md b/.actual/rules/cross-cutting-authorization-checks-execute-2769.md new file mode 100644 index 000000000000..f534b54bfc75 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-checks-execute-2769.md @@ -0,0 +1,38 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Authorization Checks Execute + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, and for operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization checks MUST execute before domain validation logic in all organization user management endpoints. +- **R-AUTHZ-002** MUST: Use IAuthorizationService with typed requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources. +- **R-AUTHZ-003** MUST: Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence. +- **R-AUTHZ-004** MUST: For operations modifying collection access, load all affected collections and verify BulkCollectionOperations.ModifyUserAccess authorization before applying changes. +- **R-AUTHZ-005** MUST: Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges. +- **R-AUTHZ-006** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-AUTHZ-007** SHOULD: Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections. + +### Verify + +```bash +# Count BulkCollectionOperations authorization checks +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Verify NotFoundException thrown after AuthorizeAsync +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- Bulk operations affecting multiple organization users or collections simultaneously enforce authorization checks before modifications +- Self-service operations where users modify their own organization membership verify authorization before domain validation + + +Claude Code MUST NOT skip or defer verification. All organization user management endpoints must be audited for authorization-before-validation ordering. Authorization bypass patterns must be detected and remediated before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-checks-occur-6a87.md b/.actual/rules/cross-cutting-authorization-checks-occur-6a87.md new file mode 100644 index 000000000000..dc118c4bfdb1 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-checks-occur-6a87.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Authorization Checks Occur + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically all controllers in `Bit.Api.AdminConsole.Controllers` handling OrganizationUser entities and user-collection associations. + +### Rules + +- **R-AUTHZ-001** SHOULD: Authorization checks SHOULD occur before expensive operations such as database writes or external service calls. + +### Verify + +```bash +# Verify IAuthorizationService is injected in organization user controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called for collection modification operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in `Bit.Api.AdminConsole.Controllers` managing organization users inject `IAuthorizationService` as a private readonly field +- All endpoints modifying collection access call `AuthorizeAsync` with appropriate requirements (e.g., `BulkCollectionOperations.ModifyUserAccess`) before persistence operations +- Authorization failures consistently throw `NotFoundException()` without additional details to prevent enumeration +- Self-modification scenarios check `organizationAbility.AllowAdminAccessToAllCollectionItems` before allowing collection/group additions +- Editable and read-only collections are separated by authorization checks during updates + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST execute successfully before accepting changes to organization user controllers. Authorization checks MUST precede database writes and external service calls. Missing AuthorizeAsync calls on collection modification endpoints constitute a violation requiring remediation before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-checks-performed-781f.md b/.actual/rules/cross-cutting-authorization-checks-performed-781f.md new file mode 100644 index 000000000000..885462b1b709 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-checks-performed-781f.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Checks Performed + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization checks MUST be performed using policy-based authorization with named requirements (e.g., ManageUsersRequirement, ManageAccountRecoveryRequirement) rather than inline authorization logic. + +### Verify + +```bash +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers (excluding comments) +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- Integration tests verify authorization enforcement for each protected endpoint with unauthorized users +- Code comments document any exceptions with reference to exception ID and approval date + + +Claude Code MUST NOT skip or defer verification of authorization checks in protected controller actions. Static analysis and integration tests MUST confirm compliance before accepting changes to authorization-protected endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-configuration-applied-925c.md b/.actual/rules/cross-cutting-authorization-configuration-applied-925c.md new file mode 100644 index 000000000000..e6d5fe05c8bf --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-configuration-applied-925c.md @@ -0,0 +1,42 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authorization Configuration Applied + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTH-001** MUST: Authorization configuration MUST be applied in the ConfigureServices method before middleware pipeline configuration. +- **R-AUTH-002** MUST: Production Startup.cs files MUST contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim(). +- **R-AUTH-003** MUST: Test factory classes MUST use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs). +- **R-AUTH-004** MUST: No production configuration files MUST contain authorization policies with RequireAssertion(a => true) or other permissive assertions. +- **R-AUTH-005** SHOULD: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes. +- **R-AUTH-006** SHOULD: Use IOptions or similar configuration objects to externalize policy requirements rather than hardcoding in Startup. +- **R-AUTH-007** SHOULD: Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation. +- **R-AUTH-008** SHOULD: Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers. +- **R-AUTH-009** SHOULD: Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' + +# Verify no permissive assertions in production paths +grep -r 'RequireAssertion.*true' --include='Startup.cs' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- Authentication schemes are configured using AddAuthentication before AddAuthorization +- Policy names are defined as constants or externalized configuration rather than hardcoded strings + + +Claude Code MUST NOT skip or defer verification. All R-AUTH-00X rules marked MUST are non-negotiable. Violations in production code paths MUST cause CI/CD pipeline failure. Security team review is required for any authorization policy changes before merge to main branch. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-failures-authorizeasync-a3f2.md b/.actual/rules/cross-cutting-authorization-failures-authorizeasync-a3f2.md new file mode 100644 index 000000000000..fe4d73f6d6ba --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-failures-authorizeasync-a3f2.md @@ -0,0 +1,37 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Authorization Failures Authorizeasync + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically all controllers in `Bit.Api.AdminConsole.Controllers` handling OrganizationUser entities and sensitive multi-tenant operations. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization failures from AuthorizeAsync MUST throw NotFoundException rather than UnauthorizedException to prevent enumeration attacks. +- **R-AUTHZ-002** MUST: All controllers in Bit.Api.AdminConsole.Controllers managing organization users MUST inject IAuthorizationService as a private readonly field. +- **R-AUTHZ-003** MUST: All endpoints modifying collection access MUST call AuthorizeAsync with appropriate requirements (e.g., BulkCollectionOperations.ModifyUserAccess) before persistence operations. +- **R-AUTHZ-004** MUST: For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync. +- **R-AUTHZ-005** MUST: Self-modification scenarios MUST retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions. +- **R-AUTHZ-006** SHOULD: Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates. +- **R-AUTHZ-007** MAY: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks (EXC-001). + +### Verify + +```bash +# Verify IAuthorizationService injection in all organization user controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync calls with BulkCollectionOperations.ModifyUserAccess +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify NotFoundException thrown on authorization failures +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration +- Collection entities are fetched before authorization checks are performed +- Self-modification checks validate organizationAbility.AllowAdminAccessToAllCollectionItems + + +Claude Code MUST NOT skip or defer verification of these authorization rules. Authorization failures are security-critical and MUST be enforced consistently across all organization user management endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-failures-throw-5a99.md b/.actual/rules/cross-cutting-authorization-failures-throw-5a99.md new file mode 100644 index 000000000000..8c4b12550f99 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-failures-throw-5a99.md @@ -0,0 +1,29 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Failures Throw + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-AUTH-001** MUST: Authorization failures MUST throw NotFoundException or return appropriate HTTP error responses (400 Bad Request, 401 Unauthorized, 403 Forbidden) based on the authorization context. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + + +Claude Code MUST NOT skip or defer verification. Static code analysis tools MUST scan for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls. Integration tests MUST verify authorization enforcement for each protected endpoint with unauthorized users. Security-focused code reviews MUST check authorization logic in new and modified controller actions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-failures-throw-7ee9.md b/.actual/rules/cross-cutting-authorization-failures-throw-7ee9.md new file mode 100644 index 000000000000..5459b2f489c6 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-failures-throw-7ee9.md @@ -0,0 +1,36 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Authorization Failures Throw + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations requiring authorization enforcement, specifically HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources. + +### Rules + +- **R-AUTH-001** MUST: Authorization failures MUST throw NotFoundException or UnauthorizedAccessException to prevent information disclosure about protected resources. +- **R-AUTH-002** MUST: All protected controller actions include [Authorize] attributes with custom requirement classes. +- **R-AUTH-003** MUST: No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous]. +- **R-AUTH-004** MUST: All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions (e.g., Bit.Api.AdminConsole.Authorization.Requirements). +- **R-AUTH-005** SHOULD: Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters. +- **R-AUTH-006** SHOULD: Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence. + +### Verify + +```bash +# Count [Authorize] attributes in API controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find unprotected controller actions (public methods without [Authorize] or [AllowAnonymous]) +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- Static analysis verification commands return zero unprotected endpoints + + +Claude Code MUST NOT skip or defer verification of these authorization rules. All new controller actions must be verified against R-AUTH-002 and R-AUTH-003 before acceptance. Authorization failure behavior must be verified against R-AUTH-001 and R-AUTH-006. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-logic-not-ca94.md b/.actual/rules/cross-cutting-authorization-logic-not-ca94.md new file mode 100644 index 000000000000..e46fe5a6a48e --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-logic-not-ca94.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Logic Not + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects, specifically HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources. + +### Rules + +- **R-AUTHZ-001** MUST NOT: Authorization logic MUST NOT be implemented within action method bodies; all permission checks MUST occur via attribute-based declarative authorization. +- **R-AUTHZ-002** MUST: All controller action methods returning IResult or IActionResult MUST have either `[Authorize]`, `[Authorize]`, or `[AllowAnonymous]` attributes. +- **R-AUTHZ-003** MUST: Custom authorization requirement classes MUST implement `IAuthorizationRequirement` and have corresponding registered handler implementations. +- **R-AUTHZ-004** MUST: All custom authorization requirements MUST be registered in the dependency injection container during application startup. +- **R-AUTHZ-005** SHOULD: For actions requiring multiple authorization checks, apply multiple `[Authorize]` attributes or create composite requirement types that evaluate multiple conditions. +- **R-AUTHZ-006** SHOULD: Authorization requirement semantics SHOULD be documented in XML comments on requirement classes to aid developers in selecting appropriate attributes. +- **R-AUTHZ-007** MUST: `[AllowAnonymous]` usage MUST be justified with security review approval and documented in code comments and pull request description. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify all custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either `[Authorize]`, `[Authorize]`, or `[AllowAnonymous]` attributes +- All custom requirement classes implement `IAuthorizationRequirement` and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All `[AllowAnonymous]` usage is documented with security rationale and approved by security team + + +Claude Code MUST NOT skip or defer verification of authorization attribute presence on all controller actions. Static analysis violations MUST block pull requests until resolved. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-middleware-added-7b79.md b/.actual/rules/cross-cutting-authorization-middleware-added-7b79.md new file mode 100644 index 000000000000..a8874f44998f --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-middleware-added-7b79.md @@ -0,0 +1,38 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authorization Middleware Added + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including startup configuration, middleware pipeline setup, and controller authorization attributes. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Authorization middleware MUST be added to the request pipeline via `app.UseAuthorization()` after authentication and before controller routing. +- **R-SCIM-AUTH-002** MUST: Register authentication schemes before calling `AddAuthorization` to ensure authentication handlers are available for policy evaluation. +- **R-SCIM-AUTH-003** MUST: Place `app.UseAuthentication()` before `app.UseAuthorization()` in the Configure method to ensure claims are populated before policy evaluation. +- **R-SCIM-AUTH-004** MUST: Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity. +- **R-SCIM-AUTH-005** MUST: Production Scim policies include `RequireAuthenticatedUser` and `RequireClaim` for 'api.scim' scope. +- **R-SCIM-AUTH-006** SHOULD: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims to prevent test policy simplification from masking authorization bugs. +- **R-SCIM-AUTH-007** SHOULD: Add startup validation tests that verify policy registration and claim requirements match security specifications. +- **R-SCIM-AUTH-008** SHOULD: Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments. + +### Verify + +```bash +# Verify AddAuthorization configuration with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify api.scim scope claim requirement +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain `AddAuthorization` configuration with a named 'Scim' policy +- Production Scim policies include `RequireAuthenticatedUser` and `RequireClaim` for 'api.scim' scope +- Middleware pipeline ordering shows `UseAuthentication()` called before `UseAuthorization()` in all Configure methods +- Authorization enforcement points are established for all SCIM API endpoints under `/v2/{organizationId}/users` and `/v2/{organizationId}/groups` routes +- Controllers decorated with authorization policy attributes reference the 'Scim' named policy + + +Claude Code MUST NOT skip or defer verification of authorization middleware configuration. Pull requests missing authorization policy configuration for new SCIM endpoints MUST be blocked. Runtime authorization failures MUST return 401 Unauthorized or 403 Forbidden responses with diagnostic logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-middleware-added-f25d.md b/.actual/rules/cross-cutting-authorization-middleware-added-f25d.md new file mode 100644 index 000000000000..5af15266e12a --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-middleware-added-f25d.md @@ -0,0 +1,42 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Middleware Added + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints with policy-based authorization requirements. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization middleware MUST be added to the request pipeline via `app.UseAuthorization()` after authentication middleware. +- **R-AUTHZ-002** MUST: Authorization policies MUST be registered in `ConfigureServices`/`Startup.cs` using `services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); })`. +- **R-AUTHZ-003** MUST: Controllers or actions exposing protected endpoints MUST reference authorization policies by name using `[Authorize(Policy = "...")]` attribute decoration. +- **R-AUTHZ-004** MUST: Production authorization policies MUST require authenticated users with specific scope claims (e.g., 'api.scim') via `policy.RequireClaim()`. +- **R-AUTHZ-005** MUST: `app.UseAuthentication()` MUST be called before `app.UseAuthorization()` in the request pipeline configuration. +- **R-AUTHZ-006** MUST: Test-specific authorization policies using `RequireAssertion(a => true)` MUST be isolated to test application factories and MUST NOT appear in production `Startup.cs`. +- **R-AUTHZ-007** SHOULD: Use constants for policy names instead of string literals to prevent policy name mismatches between configuration and attribute references. +- **R-AUTHZ-008** SHOULD: Use `JwtClaimTypes` constants from IdentityModel library for standardized claim type references. + +### Verify + +```bash +# Verify AddAuthorization is configured in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policy requires api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication middleware is called before authorization middleware +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers reference authorization policies by name +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- `services.AddAuthorization()` configuration exists in `Startup.cs` with a named policy requiring authenticated users and 'api.scim' scope claim +- `app.UseAuthorization()` is called after `app.UseAuthentication()` in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using `[Authorize(Policy = "...")]` attributes +- Test application factories define separate authorization policies isolated from production configuration +- Integration tests verify unauthorized requests return 401/403 status codes +- Production `Startup.cs` does not contain test-specific authorization bypass patterns like `RequireAssertion(a => true)` + + +Claude Code MUST NOT skip or defer verification of these authorization middleware rules. All MUST-level rules require explicit confirmation before accepting code changes to SCIM endpoints or authorization configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-combine-b65c.md b/.actual/rules/cross-cutting-authorization-policies-combine-b65c.md new file mode 100644 index 000000000000..cbd0345fc5f6 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-combine-b65c.md @@ -0,0 +1,35 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Combine + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints with policy-based authorization configuration. + +### Rules + +- **R-AUTHZ-001** MAY: Authorization policies MAY combine multiple requirements (authentication, claims, assertions) within a single named policy. + +### Verify + +```bash +# Verify authorization policies are registered in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policies require api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers reference authorization policies by name +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration +- Integration tests verify unauthorized requests return 401/403 status codes +- Production Startup.cs does not contain test-specific authorization bypass patterns (RequireAssertion(a => true)) + + +Clause Code MUST NOT skip or defer verification of authorization policy configuration. All SCIM endpoints MUST be protected by named authorization policies combining authentication and scope claim requirements. Test-specific authorization bypasses MUST be isolated to test application factories and never appear in production configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-configured-4a49.md b/.actual/rules/cross-cutting-authorization-policies-configured-4a49.md new file mode 100644 index 000000000000..88694d9de91b --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-configured-4a49.md @@ -0,0 +1,32 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Policies Configured + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-AUTHZ-001** SHOULD: Authorization policies SHOULD be configured centrally using services.AddAuthorization() in application startup configuration. + +### Verify + +```bash +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- IAuthorizationService is injected as a private readonly field in controller constructors +- Custom authorization requirements implement IAuthorizationRequirement interface with corresponding AuthorizationHandler classes +- Bulk operations iterate through resources and verify authorization for each resource instance + + +Claude Code MUST NOT skip or defer verification. Static code analysis tools MUST scan for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls. Integration tests MUST verify authorization enforcement for each protected endpoint with unauthorized users. Security-focused code reviews MUST check authorization logic in new and modified controller actions. CI pipeline MUST fail if static analysis detects controller actions missing required authorization checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-configured-dbd8.md b/.actual/rules/cross-cutting-authorization-policies-configured-dbd8.md new file mode 100644 index 000000000000..b7d1889bea18 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-configured-dbd8.md @@ -0,0 +1,41 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authorization Policies Configured + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization policies MUST be configured using AddAuthorization with explicitly named policy identifiers. +- **R-AUTHZ-002** MUST: Production authorization policies MUST use RequireAuthenticatedUser() combined with RequireClaim(JwtClaimTypes.Scope, 'api.scim') or equivalent scope-based claims. +- **R-AUTHZ-003** MUST: Authentication schemes MUST be configured using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation. +- **R-AUTHZ-004** MUST: Test environments MUST NOT use permissive authorization policies (RequireAssertion(a => true)) in production code paths; such policies are restricted to test-specific configuration files only (e.g., *ApplicationFactory.cs, *TestStartup.cs). +- **R-AUTHZ-005** SHOULD: Policy names SHOULD be defined as constants in shared configuration classes and referenced in both policy configuration and controller attributes to enable compile-time verification. +- **R-AUTHZ-006** SHOULD: Authorization policy requirements (scope names, claim types) SHOULD be externalized using IOptions or similar configuration objects rather than hardcoded in Startup. +- **R-AUTHZ-007** SHOULD: Authorization policy requirements SHOULD be documented in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers. +- **R-AUTHZ-008** SHOULD: Logging SHOULD be implemented in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' + +# Verify test-specific permissive policies are isolated to test files +grep -r 'RequireAssertion.*true' --include='*.cs' | grep -E '(ApplicationFactory|TestStartup)' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- Authentication is configured via AddAuthentication before AddAuthorization is called +- Policy names are consistently referenced across policy configuration and controller attributes + + +Claude Code MUST NOT skip or defer verification. All rules marked MUST are mandatory and must be verified before accepting code changes. Security team review is required for any authorization policy changes before merge to main branch. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-named-4edb.md b/.actual/rules/cross-cutting-authorization-policies-named-4edb.md new file mode 100644 index 000000000000..708f13dfbd90 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-named-4edb.md @@ -0,0 +1,34 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Named + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints with policy-based authorization configuration. + +### Rules + +- **R-AUTHPOL-001** MUST: Authorization policies MUST be named consistently (e.g., "Scim") and referenced by name in controller authorization attributes. + +### Verify + +```bash +# Verify authorization policies are registered in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policies require api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers reference authorization policies by name +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration +- No test-specific authorization bypass patterns (RequireAssertion(a => true)) appear in production Startup.cs + + +Clause Code MUST NOT skip or defer verification of authorization policy naming consistency and policy-based attribute decoration. All SCIM endpoints MUST be protected by named authorization policies registered in service configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-registered-94d3.md b/.actual/rules/cross-cutting-authorization-policies-registered-94d3.md new file mode 100644 index 000000000000..34c3b202733f --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-registered-94d3.md @@ -0,0 +1,42 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Authorization Policies Registered + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, service configuration in Startup or Program.cs registering authorization policies, and integration test factories configuring test authentication and authorization schemes. + +### Rules + +- **R-AUTH-001** SHOULD: Authorization policies SHOULD be registered in service configuration using AddAuthorization with named policies or requirement types. +- **R-AUTH-002** MUST: All controller files containing protected endpoints MUST inject IAuthorizationService through constructor dependency injection. +- **R-AUTH-003** MUST: All resource-based authorization decisions MUST call AuthorizeAsync before granting access to protected resources. +- **R-AUTH-004** MUST: Authorization failures MUST be handled by throwing NotFoundException to prevent information disclosure about resource existence. +- **R-AUTH-005** SHOULD: Custom authorization requirements SHOULD be implemented by creating classes implementing IAuthorizationRequirement with corresponding handlers implementing AuthorizationHandler. +- **R-AUTH-006** MUST: Public endpoints that require no authorization MUST be explicitly marked with [AllowAnonymous] attribute and documented. +- **R-AUTH-007** MUST: Test environments MUST configure authorization policies separately from production configuration to prevent test policies from being deployed to production. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization registration in configuration +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count custom authorization handlers +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- All public endpoints are explicitly marked with [AllowAnonymous] attribute +- Authorization failures consistently throw NotFoundException to prevent information disclosure +- Custom authorization handlers are implemented for all authorization requirements + + +Claude Code MUST NOT skip or defer verification of these authorization rules. All protected endpoints MUST have explicit authorization checks using IAuthorizationService. Missing authorization checks are security vulnerabilities and MUST be remediated immediately. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-registered-b7a3.md b/.actual/rules/cross-cutting-authorization-policies-registered-b7a3.md new file mode 100644 index 000000000000..15dbc71809c0 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-registered-b7a3.md @@ -0,0 +1,44 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Registered + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints with ApiKeyAuthenticationHandler or equivalent authentication schemes. + +### Rules + +- **R-AUTHZ-001** MUST: Authorization policies MUST be registered using `services.AddAuthorization()` during service configuration in Startup.cs or equivalent application factory classes. +- **R-AUTHZ-002** MUST: Production authorization policies MUST require authenticated users with 'api.scim' scope claims. +- **R-AUTHZ-003** MUST: `app.UseAuthorization()` MUST be called after `app.UseAuthentication()` in the request pipeline configuration. +- **R-AUTHZ-004** MUST: Controllers or actions exposing SCIM endpoints MUST reference authorization policies by name using `[Authorize(Policy = "...")]` attributes. +- **R-AUTHZ-005** MUST: Test-specific authorization policies (e.g., `RequireAssertion(a => true)`) MUST be isolated to test application factories and MUST NOT appear in production Startup.cs. +- **R-AUTHZ-006** SHOULD: Policy names SHOULD be defined as constants rather than string literals to prevent runtime mismatches. +- **R-AUTHZ-007** SHOULD: Integration tests SHOULD verify that all referenced policy names exist in the authorization configuration. + +### Verify + +```bash +# Verify AddAuthorization is configured in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policy requires api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers use Authorize attribute with policy reference +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify test factories do not leak into production configuration +grep -r 'RequireAssertion(a => true)' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +``` + +**Accept when:** +- `services.AddAuthorization()` configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- `app.UseAuthorization()` is called after `app.UseAuthentication()` in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using `[Authorize(Policy = "...")]` attributes +- Test application factories define separate authorization policies isolated from production configuration +- Production Startup.cs does not contain test-specific authorization bypass patterns like `RequireAssertion(a => true)` +- Integration tests verify that unauthorized requests return 401/403 status codes + + +Clause Code MUST NOT skip or defer verification of these authorization policy rules. All R-AUTHZ rules marked MUST are mandatory for SCIM endpoint protection. Violations block deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-registered-fcbd.md b/.actual/rules/cross-cutting-authorization-policies-registered-fcbd.md new file mode 100644 index 000000000000..9153ec168aea --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-registered-fcbd.md @@ -0,0 +1,36 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authorization Policies Registered + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including all SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes, services implementing IScimContext and ICurrentContext interfaces, controllers decorated with authorization policy attributes, and middleware pipeline components between UseAuthentication and UseAuthorization. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Authorization policies MUST be registered using services.AddAuthorization during application startup in the ConfigureServices method. +- **R-SCIM-AUTH-002** MUST: Production Scim policies MUST include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope. +- **R-SCIM-AUTH-003** MUST: app.UseAuthentication() MUST be called before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation. +- **R-SCIM-AUTH-004** MUST: Named policies ('Scim') MUST be used consistently across startup configuration and controller authorization attributes. +- **R-SCIM-AUTH-005** SHOULD: Test environments SHOULD use simplified authorization policies with RequireAssertion(a => true) for integration testing without full authentication infrastructure. +- **R-SCIM-AUTH-006** SHOULD: Authorization-focused test suites SHOULD validate policy enforcement with realistic authentication tokens and claims to prevent test policy simplification from masking authorization bugs. + +### Verify + +```bash +# Verify AddAuthorization is configured with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify api.scim scope claim requirement +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- Named policy 'Scim' is used consistently across startup configuration and controller authorization attributes +- Test environments document policy deviations explicitly in test factory classes + + +Claude Code MUST NOT skip or defer verification of these authorization policy registration rules. All SCIM endpoints must be verified to have proper policy-based authorization enforcement in place before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-require-0cb9.md b/.actual/rules/cross-cutting-authorization-policies-require-0cb9.md new file mode 100644 index 000000000000..c01d005b85b0 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-require-0cb9.md @@ -0,0 +1,40 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authorization Policies Require + +These rules are ALWAYS ACTIVE for all SCIM service endpoints under `/v2/{organizationId}/groups` and `/v2/{organizationId}/users` routes, ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations, authorization policies named 'Scim', integration test authentication handlers, and ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods within the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Authorization policies MUST require authenticated users and enforce scope claims using RequireClaim with JwtClaimTypes.Scope value 'api.scim'. +- **R-SCIM-AUTH-002** MUST: Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization(). +- **R-SCIM-AUTH-003** MUST: Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-AUTH-004** MUST: Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-AUTH-005** MUST: Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim'). +- **R-SCIM-AUTH-006** SHOULD: Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy configuration +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers are isolated +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline +- ApiKeyAuthenticationHandler properly validates credentials and populates scope claims + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for SCIM service authentication and authorization configuration. Violations must be flagged during code review and security audit phases. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-policies-use-6910.md b/.actual/rules/cross-cutting-authorization-policies-use-6910.md new file mode 100644 index 000000000000..273d60a60948 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-policies-use-6910.md @@ -0,0 +1,29 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Authorization Policies Use + +These rules are ALWAYS ACTIVE for all files matching the configured scope. + +### Rules + +- **R-DI-001** SHOULD: Authorization policies SHOULD use RequireAssertion for complex claim-based authorization logic that cannot be expressed through simple role or claim requirements. + +### Verify + +```bash +# Verify active use of dependency injection patterns +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration is present +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Verify test factory classes exist with service collection configuration +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + + +Claude Code MUST NOT skip or defer verification. Service registration patterns and authorization policy configuration MUST be validated through code review and static analysis to ensure dependency injection boundaries are properly enforced. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirement-classes-2368.md b/.actual/rules/cross-cutting-authorization-requirement-classes-2368.md new file mode 100644 index 000000000000..8c3d4bad3d08 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirement-classes-2368.md @@ -0,0 +1,40 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Requirement Classes + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects, specifically for HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources. + +### Rules + +- **R-AUTHZ-001** MUST: All controller action methods returning IResult or IActionResult MUST have either [Authorize], [Authorize], or [AllowAnonymous] attributes declared. +- **R-AUTHZ-002** SHOULD: Authorization requirement classes SHOULD be organized in dedicated Authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) for discoverability. +- **R-AUTHZ-003** MUST: Custom authorization requirement classes MUST implement IAuthorizationRequirement marker interface. +- **R-AUTHZ-004** MUST: All custom authorization requirements MUST have corresponding registered AuthorizationHandler or AuthorizationHandler implementations in the dependency injection container. +- **R-AUTHZ-005** MUST: Authorization handlers MUST be registered during application startup in Program.cs or Startup.cs. +- **R-AUTHZ-006** SHOULD: Complex authorization requirements SHOULD use composite requirement types for common permission combinations rather than attribute proliferation. +- **R-AUTHZ-007** MUST: [AllowAnonymous] usage MUST be documented with security rationale in code comments and justified in pull request descriptions. +- **R-AUTHZ-008** MUST: All [AllowAnonymous] usage MUST receive security team review and approval during pull request review. +- **R-AUTHZ-009** SHOULD: Authorization requirement classes SHOULD include XML comments documenting authorization requirement semantics to aid developer selection. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find requirement classes that don't implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All [AllowAnonymous] endpoints are documented with security rationale and approved by security team +- No controller actions exist without authorization attributes (except those explicitly approved as exceptions) + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for controller authorization implementation. Static analysis failures MUST block pull requests until authorization attributes are added or [AllowAnonymous] is justified with security review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirement-classes-e999.md b/.actual/rules/cross-cutting-authorization-requirement-classes-e999.md new file mode 100644 index 000000000000..8c6cc36a4743 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirement-classes-e999.md @@ -0,0 +1,41 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Authorization Requirement Classes + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations requiring authorization enforcement, particularly those in the Api and AdminConsole projects that access protected organizational or user resources. + +### Rules + +- **R-AUTH-001** MUST: Authorization requirement classes MUST be defined in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements). +- **R-AUTH-002** MUST: All protected controller actions accessing organizational or user resources MUST include [Authorize] attributes with custom requirement classes. +- **R-AUTH-003** MUST: Authorization failures MUST throw NotFoundException or UnauthorizedAccessException as appropriate to prevent information disclosure about resource existence. +- **R-AUTH-004** MUST: Custom requirement classes MUST use consistent naming conventions with a *Requirement suffix and be organized in dedicated authorization namespaces. +- **R-AUTH-005** SHOULD: Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership). +- **R-AUTH-006** SHOULD: Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it. +- **R-AUTH-007** MAY: Public endpoints explicitly marked with [AllowAnonymous] are exempt from authorization requirements and MUST include justification in code comments. + +### Verify + +```bash +# Count [Authorize<*Requirement>] attributes in Api controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find controller actions without authorization attributes +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Verify authorization requirement classes exist in dedicated namespaces +find src/Api -path "*/Authorization/Requirements/*" -name "*Requirement.cs" | wc -l +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions (e.g., *Requirement suffix) +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- All [AllowAnonymous] attributes include justification comments explaining why the endpoint is public +- Authorization requirement classes are documented with clear descriptions of permissions and organizational roles + + +Claude Code MUST NOT skip or defer verification. Static analysis failures block pull request merging until authorization attributes are added. Code review process requires explicit justification for any [AllowAnonymous] usage. Security team review is required for any new custom requirement classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirements-billing-3f88.md b/.actual/rules/cross-cutting-authorization-requirements-billing-3f88.md new file mode 100644 index 000000000000..42bab7bf2cd3 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirements-billing-3f88.md @@ -0,0 +1,34 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Authorization Requirements Billing + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address operations, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-AUTH-001** MUST: All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters be decorated with `[Authorize]`. +- **R-BILLING-AUTH-002** MUST: All Organization parameters in billing endpoints be marked with `[BindNever]` attribute to prevent model binding from route parameters or request body. +- **R-BILLING-AUTH-003** MUST: Organization entities be injected via `[InjectOrganization]` attribute and never constructed from route parameters or request body data. +- **R-BILLING-AUTH-004** SHOULD: Billing-specific authorization requirements be defined in the Bit.Api.Billing.Models.Requirements namespace, separate from general administrative requirements in Bit.Api.AdminConsole.Authorization.Requirements. +- **R-BILLING-AUTH-005** SHOULD: The three-attribute pattern (`[Authorize]`, `[InjectOrganization]`, `[BindNever]`) be consistently applied across all billing endpoints with uniform parameter naming (organization). + +### Verify + +```bash +# Check for billing controllers missing authorization requirement +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters have [BindNever] protection +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with `[Authorize]` +- All Organization parameters in billing endpoints are marked with `[BindNever]` and injected via `[InjectOrganization]` +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- Billing-specific authorization requirements are located in Bit.Api.Billing.Models.Requirements namespace + + +Claude Code MUST NOT skip or defer verification. Static analysis using custom Roslyn analyzers MUST detect billing controller methods missing required authorization attributes. Code review MUST verify the three-attribute pattern on all organization billing endpoints. Integration tests MUST verify authorization enforcement by attempting to access billing endpoints without proper organization permissions. CI pipeline MUST fail when static analysis detects missing authorization attributes. Security team approval is REQUIRED for any billing endpoint that does not use ManageOrganizationBillingRequirement. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirements-declared-3c80.md b/.actual/rules/cross-cutting-authorization-requirements-declared-3c80.md new file mode 100644 index 000000000000..5c73a6139416 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirements-declared-3c80.md @@ -0,0 +1,30 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Authorization Requirements Declared + +These rules are ALWAYS ACTIVE for all internal API endpoint implementations in the AdminConsole and Admin controllers requiring authorization enforcement. + +### Rules + +- **R-AUTH-001** MUST: Authorization requirements MUST be declared using ASP.NET Core's attribute-based authorization model at the controller action level. + +### Verify + +```bash +# Count authorization attributes on internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Verify public endpoints have AllowAnonymous attribute +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes +- Public endpoints are explicitly marked with [AllowAnonymous] attribute and include security rationale in code comments + + +Claude Code MUST NOT skip or defer verification. All internal API endpoints must have authorization attributes applied before code review approval. CI pipeline MUST fail if security tests detect endpoints without required authorization attributes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirements-enforced-e334.md b/.actual/rules/cross-cutting-authorization-requirements-enforced-e334.md new file mode 100644 index 000000000000..b37db5a83af5 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirements-enforced-e334.md @@ -0,0 +1,36 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Authorization Requirements Enforced + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, and for operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** SHOULD: Authorization requirements SHOULD be enforced declaratively using [Authorize] attributes where possible, falling back to imperative checks for complex scenarios. +- **R-AUTHZ-002** MUST: Authorization checks using IAuthorizationService MUST be performed before domain validation logic in all organization user management endpoints. +- **R-AUTHZ-003** MUST: Failed authorization checks MUST throw NotFoundException rather than UnauthorizedException or ForbiddenException to prevent information disclosure about resource existence. +- **R-AUTHZ-004** MUST: Collection access modification operations MUST verify BulkCollectionOperations.ModifyUserAccess authorization for all affected collections before applying changes. +- **R-AUTHZ-005** MUST: Organization abilities (AllowAdminAccessToAllCollectionItems) MUST be checked before allowing self-modification operations that could escalate privileges. +- **R-AUTHZ-006** SHOULD: Authorization result caching within request scope SHOULD be implemented for bulk operations to mitigate performance degradation from multiple authorization checks. + +### Verify + +```bash +# Count AuthorizeAsync calls with BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Verify NotFoundException is thrown after AuthorizeAsync in OrganizationUsersController +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- Organization abilities are checked before allowing self-modification operations that could escalate privileges + + +Claude Code MUST NOT skip or defer verification of authorization enforcement patterns. All new organization user management endpoints MUST be reviewed for compliance with R-AUTHZ-001 through R-AUTHZ-006 before approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-requirements-named-db81.md b/.actual/rules/cross-cutting-authorization-requirements-named-db81.md new file mode 100644 index 000000000000..c2dd758b663b --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-requirements-named-db81.md @@ -0,0 +1,31 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Authorization Requirements Named + +These rules are ALWAYS ACTIVE for all API controller endpoints requiring authorization in the AdminConsole API surface, specifically controllers in the Bit.Api.AdminConsole namespace handling sensitive operations including policy management, organization invite links, and provider-organization relationships. + +### Rules + +- **R-AUTHZ-001** SHOULD: Authorization requirements SHOULD be named with a `Requirement` suffix to clearly identify them as authorization requirement types. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async Task methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes following naming convention +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either `[Authorize]` or `[AllowAnonymous]` attributes +- All requirement classes are defined in `Bit.Api.AdminConsole.Authorization` namespace or subnamespaces and follow the `Requirement` naming suffix convention +- No controller methods use string-based `Authorize(Policy = "...")` attributes for authorization requirements +- Endpoints explicitly marked with `[AllowAnonymous]` (e.g., token-based policy retrieval, health checks) are documented +- Deprecated endpoints maintaining backward compatibility are documented as exceptions + + +Claude Code MUST NOT skip or defer verification. All new or modified controller methods in the AdminConsole API surface MUST be verified to comply with the authorization attribute requirements before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-authorization-verification-tests-2daa.md b/.actual/rules/cross-cutting-authorization-verification-tests-2daa.md new file mode 100644 index 000000000000..f60380720993 --- /dev/null +++ b/.actual/rules/cross-cutting-authorization-verification-tests-2daa.md @@ -0,0 +1,30 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Authorization Verification Tests + +These rules are ALWAYS ACTIVE for all API controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes and their corresponding unit test projects using Xunit framework. + +### Rules + +- **R-AUTH-001** MUST: Authorization verification tests MUST throw Xunit.Sdk.FailException with descriptive error messages identifying missing attributes and affected controllers/methods. + +### Verify + +```bash +# Count authorization verification test invocations +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run authorization verification tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes on controllers +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- Authorization verification tests fail with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization when violations are detected + + +Claude Code MUST NOT skip or defer verification of authorization attributes on API controllers. All public HTTP action methods (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST be verified to have appropriate authorization attributes via unit tests before code is approved. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-base64-encoding-decoding-0aee.md b/.actual/rules/cross-cutting-base64-encoding-decoding-0aee.md new file mode 100644 index 000000000000..278c542182b0 --- /dev/null +++ b/.actual/rules/cross-cutting-base64-encoding-decoding-0aee.md @@ -0,0 +1,38 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Base64 Encoding Decoding + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, string marshaling code in lib.rs and cipher.rs modules, and base64 encoding/decoding operations for binary cryptographic data crossing FFI boundaries. + +### Rules + +- **R-FFI-001** MUST: All CStr::from_ptr conversions MUST be contained within unsafe blocks with explicit null pointer validation using is_null() before dereferencing. +- **R-FFI-002** MUST: A public free_c_string function MUST exist and be documented for C callers to deallocate returned strings allocated by the Rust SDK. +- **R-FFI-003** MUST: FFI functions in lib.rs and cipher.rs MUST consistently use CStr/CString for string parameter marshaling across the FFI boundary. +- **R-FFI-004** SHOULD: Base64 encoding/decoding of binary cryptographic data crossing FFI boundaries SHOULD use the standard engine from the base64 crate for consistent encoding behavior. +- **R-FFI-005** MUST: Memory ownership contracts MUST be documented in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called. + +### Verify + +```bash +# Verify all CStr::from_ptr calls are in unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists and is public +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +# Verify base64 standard engine usage +grep -r "base64::engine::general_purpose::STANDARD" util/RustSdk/rust/src/ && echo "PASS: standard engine in use" || echo "FAIL" +``` + +**Accept when:** +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data +- Memory ownership contracts are documented in function comments for all FFI string functions + + +Claude Code MUST NOT skip or defer verification. All FFI string handling MUST comply with CStr/CString validation patterns before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-billing-endpoints-that-b5d9.md b/.actual/rules/cross-cutting-billing-endpoints-that-b5d9.md new file mode 100644 index 000000000000..8f21f15c6a29 --- /dev/null +++ b/.actual/rules/cross-cutting-billing-endpoints-that-b5d9.md @@ -0,0 +1,35 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Billing Endpoints That + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address modifications, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-001** MUST: Billing endpoints that modify organization state (subscription updates, billing address changes, payment method updates) MUST enforce the same authorization requirement as read operations. +- **R-BILLING-002** MUST: All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize]. +- **R-BILLING-003** MUST: All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization]. +- **R-BILLING-004** MUST: Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering. +- **R-BILLING-005** MUST: Billing-specific authorization requirements are placed in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements. + +### Verify + +```bash +# Check for billing controllers missing authorization attributes +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters have [BindNever] protection +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- No billing endpoints construct Organization entities from route parameters or request body data +- All billing-specific authorization requirements are located in Bit.Api.Billing.Models.Requirements namespace + + +Claude Code MUST NOT skip or defer verification. Static analysis using custom Roslyn analyzers MUST detect billing controller methods missing required authorization attributes. Code review MUST verify the three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) on all organization billing endpoints. Integration tests MUST verify authorization enforcement by attempting to access billing endpoints without proper organization permissions. CI pipeline MUST fail when static analysis detects missing authorization attributes. Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-boundaries-coordinate-multiple-7266.md b/.actual/rules/cross-cutting-boundaries-coordinate-multiple-7266.md new file mode 100644 index 000000000000..8aa3c10cd234 --- /dev/null +++ b/.actual/rules/cross-cutting-boundaries-coordinate-multiple-7266.md @@ -0,0 +1,29 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Boundaries Coordinate Multiple + +These rules are ALWAYS ACTIVE for all API controller classes and service boundary implementations in this project. + +### Rules + +- **R-CQSAE-001** MAY: API boundaries MAY coordinate multiple command or query operations within a single endpoint method when representing a cohesive business operation. + +### Verify + +```bash +# Verify all API controller action methods use async Task signatures +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controller classes (DbContext, SaveChanges, Query, Execute) +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files using async/await patterns with interface method invocations +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + + +Clause Code MUST NOT skip or defer verification. All new API controllers and modifications to existing controllers must satisfy these acceptance criteria before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-build-scripts-declare-d7c8.md b/.actual/rules/cross-cutting-build-scripts-declare-d7c8.md new file mode 100644 index 000000000000..5c4588fc74ee --- /dev/null +++ b/.actual/rules/cross-cutting-build-scripts-declare-d7c8.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Build Scripts Declare + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs) responsible for generating language bindings and test fixtures used for cryptographic operation testing. + +### Rules + +- **R-CSHARP-FFI-001** MUST: Build scripts MUST declare all Rust source files containing extern functions as inputs to the binding generator using `input_extern_file`. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Verify test fixture naming conventions are in place +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated C# bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains `csbindgen::Builder` configuration with `input_extern_file`, `csharp_dll_name`, `csharp_namespace`, and `generate_csharp_file` calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., `_FAKE_*`, `_TEST_*`) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Claude Code MUST NOT skip or defer verification. Automated CI checks MUST verify that build.rs successfully generates C# bindings and that generated files compile. Code review MUST check for proper use of csbindgen configuration and test fixture naming conventions. Static analysis tools MUST scan for usage of test constants in non-test production code paths. Violations result in CI build failures, code review rejection, or security review escalation as appropriate. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-bulk-operations-verify-d6b9.md b/.actual/rules/cross-cutting-bulk-operations-verify-d6b9.md new file mode 100644 index 000000000000..90d571860034 --- /dev/null +++ b/.actual/rules/cross-cutting-bulk-operations-verify-d6b9.md @@ -0,0 +1,34 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Bulk Operations Verify + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-BULK-001** MUST: Bulk operations MUST verify authorization for each affected resource using BulkCollectionOperations or equivalent authorization operations. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers (excluding comments) +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +# Verify bulk operation authorization patterns +grep -r 'foreach.*AuthorizeAsync' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- Bulk operations iterate through resources and verify authorization for each resource using BulkCollectionOperations or equivalent patterns +- Approved exceptions are documented in code comments with reference to exception ID and approval date + + +Claude Code MUST NOT skip or defer verification. Static code analysis tools MUST scan for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls. Integration tests MUST verify authorization enforcement for each protected endpoint with unauthorized users. Security-focused code reviews MUST check authorization logic in new and modified controller actions. CI pipeline MUST fail if static analysis detects controller actions missing required authorization checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-configuration-integrate-4625.md b/.actual/rules/cross-cutting-cache-configuration-integrate-4625.md new file mode 100644 index 000000000000..578f14f9dcd6 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-configuration-integrate-4625.md @@ -0,0 +1,38 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Configuration Integrate + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in the Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-CACHE-001** MUST: All service registration code using distributed Redis caching MUST use AddExtendedCache instead of direct AddStackExchangeRedisCache calls. +- **R-CACHE-002** MUST: Cache configuration MUST integrate with Bit.Core.Settings for connection string and configuration management. +- **R-CACHE-003** MUST: Redis connection error logging MUST include cache name context via ILogger.LogError. +- **R-CACHE-004** MUST: No direct ConnectionMultiplexer.Connect calls SHALL exist outside ExtendedCacheServiceCollectionExtensions. +- **R-CACHE-005** SHOULD: ILogger SHOULD be registered in the service collection before calling AddExtendedCache to enable connection error logging. + +### Verify + +```bash +# Verify AddExtendedCache usage across service registration points +grep -r 'AddExtendedCache' --include='*.cs' / + +# Detect direct AddStackExchangeRedisCache calls outside approved extension +grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +# Detect direct ConnectionMultiplexer.Connect outside extension +grep -r 'ConnectionMultiplexer\.Connect' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions +- ILogger is registered in the service collection before AddExtendedCache invocation +- Redis connection strings are configured via Bit.Core.Settings + + +Claude Code MUST NOT skip or defer verification. CI pipeline MUST fail if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions. Pull requests with non-compliant cache registration MUST be blocked until migrated to AddExtendedCache. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-configuration-use-49c3.md b/.actual/rules/cross-cutting-cache-configuration-use-49c3.md new file mode 100644 index 000000000000..9120a5eb8595 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-configuration-use-49c3.md @@ -0,0 +1,41 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Configuration Use + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, and Redis connection management for cache instances. + +### Rules + +- **R-CACHE-001** MUST: Cache configuration MUST use ConnectionMultiplexer.Connect with connection strings sourced from Bit.Core.Settings. +- **R-CACHE-002** MUST: All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities. +- **R-CACHE-003** MUST: Redis connection failures are logged with LogError including cache name and exception details. +- **R-CACHE-004** SHOULD: Implement IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints. +- **R-CACHE-005** SHOULD: Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment. + +### Verify + +```bash +# Verify StackExchange.Redis package is present in Core project +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify AddExtendedCache is used for all distributed cache registrations +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify ConnectionMultiplexer.Connect is used for cache configuration +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +# Verify no direct RedisCacheOptions configuration outside approved extension methods +grep -r 'new RedisCacheOptions' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify error logging for Redis connection failures +grep -r 'LogError.*cache' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- No direct RedisCacheOptions configuration exists outside ExtendedCacheServiceCollectionExtensions +- Connection strings are sourced from Bit.Core.Settings + + +Claude Code MUST NOT skip or defer verification. All R-CACHE rules are mandatory for cache configuration code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-configuration-use-f590.md b/.actual/rules/cross-cutting-cache-configuration-use-f590.md new file mode 100644 index 000000000000..7e8290757ef6 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-configuration-use-f590.md @@ -0,0 +1,39 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Configuration Use + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in the Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-CACHE-001** MUST: Cache configuration MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client implementation. +- **R-CACHE-002** MUST: All service registration code using distributed Redis caching MUST use AddExtendedCache instead of direct AddStackExchangeRedisCache calls. +- **R-CACHE-003** MUST: Redis connection error logging MUST include cache name context via ILogger.LogError. +- **R-CACHE-004** MUST: No direct ConnectionMultiplexer.Connect calls MUST exist outside ExtendedCacheServiceCollectionExtensions. +- **R-CACHE-005** MUST: ILogger MUST be registered in the service collection before calling AddExtendedCache to enable connection error logging. +- **R-CACHE-006** SHOULD: Redis connection strings SHOULD be configured via Bit.Core.Settings to maintain consistency with the extension's expected configuration source. + +### Verify + +```bash +# Verify AddExtendedCache usage across service registration points +grep -r 'AddExtendedCache' --include='*.cs' . + +# Detect direct AddStackExchangeRedisCache calls outside approved extension methods +grep -r 'AddStackExchangeRedisCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' . + +# Detect direct ConnectionMultiplexer.Connect calls outside approved extension +grep -r 'ConnectionMultiplexer\.Connect' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions' +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions +- ILogger is registered in service collection before AddExtendedCache invocation +- Redis connection strings are sourced from Bit.Core.Settings configuration + + +Claude Code MUST NOT skip or defer verification. Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods MUST fail the CI pipeline. Pull requests with non-compliant cache registration MUST be blocked until migrated to AddExtendedCache. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-implementations-expose-f10e.md b/.actual/rules/cross-cutting-cache-implementations-expose-f10e.md new file mode 100644 index 000000000000..5b754852d6fb --- /dev/null +++ b/.actual/rules/cross-cutting-cache-implementations-expose-f10e.md @@ -0,0 +1,35 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Implementations Expose + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, Redis connection management and error handling for cache instances, and cache configuration sourced from Bit.Core.Settings. + +### Rules + +- **R-CACHE-001** SHOULD: Cache implementations SHOULD expose the IDistributedCache interface for compatibility with standard ASP.NET Core caching patterns. +- **R-CACHE-002** MUST: All distributed cache registrations MUST use AddExtendedCache from Bit.Core.Utilities. +- **R-CACHE-003** MUST: Redis connection failures MUST be logged with LogError including cache name and exception details. +- **R-CACHE-004** MUST: Direct RedisCacheOptions configuration outside approved extension methods MUST NOT be used. +- **R-CACHE-005** MUST: Microsoft.Extensions.Caching.StackExchangeRedis package reference MUST exist in Core project dependencies. + +### Verify + +```bash +# Verify StackExchange.Redis package is referenced +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify AddExtendedCache is used for cache registration +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify ConnectionMultiplexer usage patterns +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- No direct RedisCacheOptions configuration exists outside ExtendedCacheServiceCollectionExtensions +- IDistributedCache interface is exposed by all cache implementations + + +Claude Code MUST NOT skip or defer verification. All rules must be validated before approving cache infrastructure changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-implementations-use-92c0.md b/.actual/rules/cross-cutting-cache-implementations-use-92c0.md new file mode 100644 index 000000000000..90e322818935 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-implementations-use-92c0.md @@ -0,0 +1,38 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Cache Implementations Use + +These rules are ALWAYS ACTIVE for all distributed caching implementations in Bit.Core and dependent services that use Redis-backed cache implementations registered through dependency injection. + +### Rules + +- **R-CACHE-001** SHOULD: Cache implementations SHOULD use TryAdd patterns (e.g., TryAddSingleton) from Microsoft.Extensions.DependencyInjection.Extensions to avoid duplicate registrations. +- **R-CACHE-002** MUST: All distributed cache usage in the codebase MUST use IDistributedCache interface rather than direct Redis client references. +- **R-CACHE-003** MUST: Service collection registration for distributed cache MUST be performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities. +- **R-CACHE-004** MUST: Redis connection failures MUST be logged with structured logging including cache name context. +- **R-CACHE-005** MUST: No direct StackExchangeRedis client usage is permitted outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer. + +### Verify + +```bash +# Verify IDistributedCache usage without direct Redis client references +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify IDistributedCache injection patterns +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration usage +grep -r 'AddExtendedCache' --include='*.cs' + +# Verify no direct ConnectionMultiplexer usage outside infrastructure +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer +- TryAdd patterns are used in service collection extensions to prevent duplicate registrations + + +Clause Code MUST NOT skip or defer verification of these rules. Pull requests introducing direct Redis client usage outside infrastructure layer MUST be blocked pending refactoring. Existing violations MUST be tracked as technical debt items and prioritized for remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-registration-encapsulated-b774.md b/.actual/rules/cross-cutting-cache-registration-encapsulated-b774.md new file mode 100644 index 000000000000..80f1ccd5ae75 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-registration-encapsulated-b774.md @@ -0,0 +1,37 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Cache Registration Encapsulated + +These rules are ALWAYS ACTIVE for all distributed caching implementations, service collection extensions, and Redis integration code within Bit.Core and dependent services. + +### Rules + +- **R-CACHE-001** SHOULD: Cache registration SHOULD be encapsulated in service collection extension methods (e.g., AddExtendedCache) within Bit.Core.Utilities. +- **R-CACHE-002** MUST: All distributed cache usage in the codebase MUST use IDistributedCache interface rather than direct Redis client references. +- **R-CACHE-003** MUST: Service collection registration for distributed cache MUST be performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities. +- **R-CACHE-004** MUST: Redis connection failures MUST be logged with structured logging including cache name context. +- **R-CACHE-005** MUST: No direct StackExchangeRedis client usage SHALL exist outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer. + +### Verify + +```bash +# Verify IDistributedCache usage without direct Redis client references +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify IDistributedCache injection and usage +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration is used +grep -r 'AddExtendedCache' --include='*.cs' + +# Verify no direct ConnectionMultiplexer usage outside infrastructure +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + + +Clause Code MUST NOT skip or defer verification of these rules. Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring. Existing violations are tracked as technical debt items and prioritized for remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-service-registration-1246.md b/.actual/rules/cross-cutting-cache-service-registration-1246.md new file mode 100644 index 000000000000..d09305f8750e --- /dev/null +++ b/.actual/rules/cross-cutting-cache-service-registration-1246.md @@ -0,0 +1,30 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Service Registration + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, Redis connection management and error handling for cache instances, and cache configuration sourced from Bit.Core.Settings. + +### Rules + +- **R-CACHE-001** SHOULD: Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to allow override by consuming applications. + +### Verify + +```bash +# Verify StackExchange.Redis package is referenced in Core project +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify AddExtendedCache is used for all distributed cache registrations +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify ConnectionMultiplexer usage patterns +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- Cache service registration uses TryAdd methods to permit consumer override + + +Clause Code MUST NOT skip or defer verification. Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review. Alternative cache providers require ADR documentation justifying deviation from standard. Missing error handling for Redis connection failures blocks merge until logging is added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-service-registration-175e.md b/.actual/rules/cross-cutting-cache-service-registration-175e.md new file mode 100644 index 000000000000..65a32c7e71ed --- /dev/null +++ b/.actual/rules/cross-cutting-cache-service-registration-175e.md @@ -0,0 +1,29 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Service Registration + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-CACHE-001** MUST: Cache service registration MUST use ExtendedCacheServiceCollectionExtensions.AddExtendedCache as the public API contract for all distributed Redis caching setup. + +### Verify + +```bash +# Verify AddExtendedCache is used for cache registration +grep -r 'AddExtendedCache' --include='*.cs' . + +# Detect direct AddStackExchangeRedisCache calls outside the extension +grep -r 'AddStackExchangeRedisCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' . +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + + +Claude Code MUST NOT skip or defer verification. Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods will cause CI pipeline failure. Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-service-registration-2dcf.md b/.actual/rules/cross-cutting-cache-service-registration-2dcf.md new file mode 100644 index 000000000000..cacfeb7a23b2 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-service-registration-2dcf.md @@ -0,0 +1,31 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Service Registration + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in the Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-CACHE-001** SHOULD: Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to prevent duplicate registrations. + +### Verify + +```bash +# Verify AddExtendedCache is used for cache registration +grep -r 'AddExtendedCache' --include='*.cs' / + +# Verify no direct AddStackExchangeRedisCache calls outside ExtendedCacheServiceCollectionExtensions +grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify Redis connection error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions +- ILogger is registered in the service collection before AddExtendedCache is called +- Redis connection strings are configured via Bit.Core.Settings + + +Claude Code MUST NOT skip or defer verification of these rules during code review. All cache service registrations MUST be audited against R-CACHE-001 to ensure consistent use of TryAdd patterns and centralized AddExtendedCache extension methods. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-service-registration-46f7.md b/.actual/rules/cross-cutting-cache-service-registration-46f7.md new file mode 100644 index 000000000000..4345bba5802d --- /dev/null +++ b/.actual/rules/cross-cutting-cache-service-registration-46f7.md @@ -0,0 +1,35 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Cache Service Registration + +These rules are ALWAYS ACTIVE for all cache service registration extensions and distributed cache initialization code that uses StackExchangeRedis or ConnectionMultiplexer.Connect operations. + +### Rules + +- **R-CACHE-001** SHOULD: Cache service registration extensions SHOULD wrap ConnectionMultiplexer.Connect calls in try-catch blocks to capture connection exceptions. +- **R-CACHE-002** SHOULD: Error logging SHOULD use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: `logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName)`. +- **R-CACHE-003** SHOULD: Connection string credentials SHOULD be sanitized before logging to avoid credential leakage in logs. +- **R-CACHE-004** SHOULD: ILogger instances SHOULD be injected into service collection extension methods via IServiceProvider or factory patterns. +- **R-CACHE-005** MAY: Correlation IDs or request context MAY be added to error logs for distributed tracing integration. + +### Verify + +```bash +# Verify Redis connection error logging is present +grep -r 'LogError.*Failed to connect to Redis' src/ + +# Count ConnectionMultiplexer.Connect calls wrapped with try-catch +grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' + +# Run cache initialization tests with detailed output +dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters +- Connection strings are sanitized and do not appear in log output +- ILogger instances are properly injected or configured before cache service registration + + +Claude Code MUST NOT skip or defer verification. All cache service registration code introducing ConnectionMultiplexer.Connect calls MUST include try-catch error logging. Static analysis and code review MUST flag violations. Production incidents involving unlogged cache failures trigger retrospective reviews. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cache-service-registration-b5a1.md b/.actual/rules/cross-cutting-cache-service-registration-b5a1.md new file mode 100644 index 000000000000..e77457594a14 --- /dev/null +++ b/.actual/rules/cross-cutting-cache-service-registration-b5a1.md @@ -0,0 +1,30 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Service Registration + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, Redis connection management and error handling for cache instances, and cache configuration sourced from Bit.Core.Settings. + +### Rules + +- **R-CACHE-001** MUST: Cache service registration MUST be performed through the ExtendedCacheServiceCollectionExtensions.AddExtendedCache extension method in Bit.Core.Utilities. + +### Verify + +```bash +# Verify StackExchange.Redis package is referenced in Core project +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify AddExtendedCache is used for all distributed cache registrations +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify no direct ConnectionMultiplexer.Connect calls outside approved extension methods +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- No direct RedisCacheOptions configuration exists outside ExtendedCacheServiceCollectionExtensions + + +Claude Code MUST NOT skip or defer verification. All distributed cache registrations must be reviewed to confirm they use the approved AddExtendedCache extension method. Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review and must be blocked until remediated. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-collection-access-modifications-3ddb.md b/.actual/rules/cross-cutting-collection-access-modifications-3ddb.md new file mode 100644 index 000000000000..2a2d8063c58b --- /dev/null +++ b/.actual/rules/cross-cutting-collection-access-modifications-3ddb.md @@ -0,0 +1,37 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Collection Access Modifications + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, and for operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** MUST: Collection access modifications MUST verify BulkCollectionOperations.ModifyUserAccess authorization for all affected collections before applying changes. +- **R-AUTHZ-002** MUST: All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic. +- **R-AUTHZ-003** MUST: Failed authorization checks MUST consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException to prevent information disclosure about resource existence. +- **R-AUTHZ-004** MUST: For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes. +- **R-AUTHZ-005** MUST: Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections. +- **R-AUTHZ-006** MUST: Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges. +- **R-AUTHZ-007** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-AUTHZ-008** SHOULD: Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation. + +### Verify + +```bash +# Count authorization checks using BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Count NotFoundException throws preceded by AuthorizeAsync calls +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic. +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException. +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes. +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers. + + +Claude Code MUST NOT skip or defer verification. Authorization checks must precede all domain validation logic in organization user management endpoints. All authorization failures must throw NotFoundException to prevent information disclosure in multi-tenant environments. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-context-classes-include-80d4.md b/.actual/rules/cross-cutting-context-classes-include-80d4.md new file mode 100644 index 000000000000..0a4ce5926be8 --- /dev/null +++ b/.actual/rules/cross-cutting-context-classes-include-80d4.md @@ -0,0 +1,31 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Context Classes Include + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, particularly the primary DatabaseContext class managing application-wide entity collections and all entity types representing persistent domain models. + +### Rules + +- **R-DBSET-001** MAY: Context classes MAY include configuration methods (OnModelCreating) to define entity relationships, keys, and database-specific behaviors. + +### Verify + +```bash +# Count DbSet properties in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet declarations follow naming pattern +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming conventions +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting +- Related DbSet properties are grouped together with comments indicating domain boundaries +- Complex entity mappings use IEntityTypeConfiguration classes rather than inline OnModelCreating logic + + +Claude Code MUST NOT skip or defer verification. All DbSet registrations must be validated during code review and build verification must pass before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controller-action-methods-3351.md b/.actual/rules/cross-cutting-controller-action-methods-3351.md new file mode 100644 index 000000000000..0a30c3b47856 --- /dev/null +++ b/.actual/rules/cross-cutting-controller-action-methods-3351.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controller Action Methods + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces where authorization requirements must be declared via attributes on controller actions. + +### Rules + +- **R-AUTHZ-001** MUST NOT: Controller action methods MUST NOT implement authorization logic imperatively within method bodies when declarative attribute-based authorization can express the requirement. +- **R-AUTHZ-002** MUST: All HTTP action methods (GET, POST, PUT, DELETE) in Api.AdminConsole and Admin namespaces that require authenticated or role-based access MUST have either `[Authorize]` or `[AllowAnonymous]` attributes applied. +- **R-AUTHZ-003** MUST: Custom authorization requirement types MUST be defined in dedicated Authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements). +- **R-AUTHZ-004** MUST: Each custom requirement type MUST have a corresponding `IAuthorizationHandler` implementation registered in the dependency injection container. +- **R-AUTHZ-005** SHOULD: Requirement type names SHOULD be descriptive and clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement). +- **R-AUTHZ-006** SHOULD: Endpoints that intentionally allow anonymous access SHOULD explicitly apply `[AllowAnonymous]` to document the decision. +- **R-AUTHZ-007** MAY: Legacy endpoints requiring complex, multi-step authorization logic that cannot be expressed declaratively MAY implement imperative authorization checks (Exception: EXC-001). +- **R-AUTHZ-008** MAY: Token-based public endpoints (e.g., invite links) MAY use `[AllowAnonymous]` with imperative token validation within the method body (Exception: EXC-002). + +### Verify + +```bash +# Scan for controller action methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization using statements +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either `[Authorize]` or `[AllowAnonymous]` attributes. +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively. +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI. +- All public endpoints explicitly marked with `[AllowAnonymous]` are documented with rationale. + + +Claude Code MUST NOT skip or defer verification. All controller action methods must be scanned for missing authorization attributes. CI builds MUST fail if controller actions lack authorization attributes and are not explicitly marked as public or anonymous. Pull requests with authorization violations MUST be blocked from merge until attributes are added or exceptions are documented and approved by the security team. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controller-action-methods-981f.md b/.actual/rules/cross-cutting-controller-action-methods-981f.md new file mode 100644 index 000000000000..7d1696a6bbfd --- /dev/null +++ b/.actual/rules/cross-cutting-controller-action-methods-981f.md @@ -0,0 +1,34 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controller Action Methods + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller action methods in the Api.AdminConsole and Admin namespaces that require authorization enforcement. + +### Rules + +- **R-AUTHZ-001** MUST: All controller action methods that require authorization MUST declare authorization requirements using the Authorize attribute with a specific requirement type (e.g., `[Authorize]`). +- **R-AUTHZ-002** MUST: Public endpoints that intentionally allow anonymous access MUST be explicitly marked with `[AllowAnonymous]` to document the decision and prevent accidental protection. +- **R-AUTHZ-003** SHOULD: Authorization requirement types SHOULD be defined in dedicated Authorization namespaces (e.g., `Bit.Api.AdminConsole.Authorization.Requirements`) to centralize authorization concerns. +- **R-AUTHZ-004** SHOULD: Custom authorization requirement types SHOULD have descriptive names that clearly communicate the authorization intent (e.g., `ManageUsersRequirement`, `ProviderAdminRequirement`). +- **R-AUTHZ-005** MAY: Complex authorization scenarios requiring multiple contextual checks MAY implement imperative authorization checks via `IAuthorizationService.AuthorizeAsync()` only when declarative attributes cannot express the requirement, and MUST be documented with security review approval. + +### Verify + +```bash +# Scan for controller action methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization using statements +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either `[Authorize]` or `[AllowAnonymous]` attributes. +- No controller action methods contain imperative authorization checks (`IAuthorizationService.AuthorizeAsync` calls) for requirements that can be expressed declaratively. +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in the dependency injection container. +- All authorization-related tests pass with no violations detected. + + +Claude Code MUST NOT skip or defer verification. All controller action methods MUST be scanned for missing authorization attributes before accepting changes. Security team notification is required for any violations detected in production code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controller-actions-not-1aa2.md b/.actual/rules/cross-cutting-controller-actions-not-1aa2.md new file mode 100644 index 000000000000..bd4c762f62c2 --- /dev/null +++ b/.actual/rules/cross-cutting-controller-actions-not-1aa2.md @@ -0,0 +1,30 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Controller Actions Not + +These rules are ALWAYS ACTIVE for all internal API endpoint implementations requiring authorization enforcement, specifically all controller actions in Bit.Api.AdminConsole.Controllers and Bit.Admin.Controllers namespaces managing organization resources and administrative functions. + +### Rules + +- **R-AUTHZ-001** MUST NOT: Controller actions MUST NOT implement authorization logic imperatively within the action method body; authorization decisions MUST be externalized to authorization handlers. + +### Verify + +```bash +# Verify authorization attributes are applied to internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Count public controller actions with authorization attributes +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific unit tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes +- No controller actions in scope implement authorization logic imperatively within the action method body + + +Claude Code MUST NOT skip or defer verification. All controller actions must be scanned for compliance with R-AUTHZ-001. Authorization logic must be externalized to handlers; imperative checks within action bodies are violations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controller-actions-that-753e.md b/.actual/rules/cross-cutting-controller-actions-that-753e.md new file mode 100644 index 000000000000..d6ef902932ee --- /dev/null +++ b/.actual/rules/cross-cutting-controller-actions-that-753e.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Controller Actions That + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects that expose HTTP action methods accessing organizational or user-scoped resources. + +### Rules + +- **R-AUTHZ-001** MUST: All controller actions that require authorization MUST declare authorization requirements using [Authorize] or [Authorize] attributes. +- **R-AUTHZ-002** MUST: Public endpoints for invite token validation or version checking require [AllowAnonymous] attribute. +- **R-AUTHZ-003** MUST: Custom authorization requirement implementations MUST extend IAuthorizationRequirement. +- **R-AUTHZ-004** MUST: All custom authorization requirements MUST have corresponding registered AuthorizationHandler implementations in the dependency injection container. +- **R-AUTHZ-005** SHOULD: Complex authorization logic involving multiple conditions SHOULD use composite requirement types rather than multiple attributes. +- **R-AUTHZ-006** SHOULD: Authorization requirement semantics SHOULD be documented in XML comments on requirement classes. +- **R-AUTHZ-007** MAY: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify all custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All [AllowAnonymous] usage is documented with security rationale in code comments and approved by security team + + +Claude Code MUST NOT skip or defer verification. All controller actions MUST be checked for authorization attributes before approval. Security team review is mandatory for any [AllowAnonymous] exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-apply-authorization-155e.md b/.actual/rules/cross-cutting-controllers-apply-authorization-155e.md new file mode 100644 index 000000000000..16490a8f7241 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-apply-authorization-155e.md @@ -0,0 +1,37 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Apply Authorization + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations requiring authorization enforcement in the Api and AdminConsole projects. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST apply authorization attributes at the action method level using the syntax `[Authorize]` where TRequirement represents the specific permission required. +- **R-AUTHZ-002** MUST: All protected controller actions accessing organizational or user resources MUST include `[Authorize]` attributes with custom requirement classes. +- **R-AUTHZ-003** MUST: Public endpoints explicitly requiring anonymous access MUST be marked with `[AllowAnonymous]` attribute with justification in code comments. +- **R-AUTHZ-004** MUST: Custom requirement classes MUST be defined in dedicated authorization namespaces (e.g., `Bit.Api.AdminConsole.Authorization.Requirements`) with consistent naming conventions using *Requirement suffix. +- **R-AUTHZ-005** MUST: Authorization failures MUST throw `NotFoundException` rather than `UnauthorizedAccessException` to prevent information disclosure about resource existence. +- **R-AUTHZ-006** SHOULD: Complex authorization scenarios requiring multiple checks SHOULD use `ICurrentContext` for supplementary runtime validation when authorization depends on request parameters. +- **R-AUTHZ-007** SHOULD: Each custom requirement class SHOULD be documented with clear descriptions of the permission it enforces and the organizational roles that satisfy it. + +### Verify + +```bash +# Count existing [Authorize] attributes +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find unprotected controller actions (public methods without [Authorize] or [AllowAnonymous]) +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +``` + +**Accept when:** +- All protected controller actions include `[Authorize]` attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked `[AllowAnonymous]` +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw `NotFoundException` or `UnauthorizedAccessException` as appropriate +- All controllers importing protected resources include `using Microsoft.AspNetCore.Authorization` + + +Claude Code MUST NOT skip or defer verification of authorization attributes on all new or modified controller actions. Static analysis failures blocking pull request merging until authorization attributes are added is mandatory. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-apply-custom-0144.md b/.actual/rules/cross-cutting-controllers-apply-custom-0144.md new file mode 100644 index 000000000000..aa3f59893540 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-apply-custom-0144.md @@ -0,0 +1,29 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Apply Custom + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST apply custom authorization requirements via Authorize attributes at the method level for endpoint-level access control. + +### Verify + +```bash +# Verify IAuthorizationService is injected in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync calls for collection modification operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + + +Claude Code MUST NOT skip or defer verification. All three verify commands must pass before accepting changes to organization user controllers. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-authorize-attributes-3853.md b/.actual/rules/cross-cutting-controllers-authorize-attributes-3853.md new file mode 100644 index 000000000000..f0b3c8c1a4a2 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-authorize-attributes-3853.md @@ -0,0 +1,29 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Authorize Attributes + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with [Authorize] attributes or custom authorization requirements that handle provider and admin operations. + +### Rules + +- **R-AUTHLOG-001** MUST: Controllers with [Authorize] attributes or custom authorization requirements MUST inject ILogger and use structured logging for all exception paths within authorized actions. + +### Verify + +```bash +# Check for controllers with [Authorize] that lack ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters (missing curly braces) +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in log statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + + +Clause Code MUST NOT skip or defer verification. All three verify commands must pass before accepting changes to authorized controller endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-bit-adminconsole-60f4.md b/.actual/rules/cross-cutting-controllers-bit-adminconsole-60f4.md new file mode 100644 index 000000000000..18beb2ad4506 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-bit-adminconsole-60f4.md @@ -0,0 +1,30 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Bit Adminconsole + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers in the Bit.Api.AdminConsole namespace managing organization user operations MUST inject IAuthorizationService as a constructor dependency. + +### Verify + +```bash +# Verify IAuthorizationService is injected in all relevant controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called for collection modification operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService as a private readonly field +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence operations +- Authorization failures consistently throw NotFoundException to prevent enumeration attacks +- Self-modification checks validate organizationAbility.AllowAdminAccessToAllCollectionItems before allowing collection/group additions + + +Claude Code MUST NOT skip or defer verification. All three verify commands must execute successfully and all accept criteria must be met before approving changes to organization user management controllers. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-bit-billing-446f.md b/.actual/rules/cross-cutting-controllers-bit-billing-446f.md new file mode 100644 index 000000000000..2db605936051 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-bit-billing-446f.md @@ -0,0 +1,35 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Controllers Bit Billing + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address operations, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-001** SHOULD: Controllers in the Bit.Api.Billing.Controllers namespace SHOULD consistently apply the organization-scoped authorization pattern across all billing-related operations. +- **R-BILLING-002** MUST: All controller methods in Bit.Api.Billing.Controllers that accept Organization parameters MUST be decorated with [Authorize]. +- **R-BILLING-003** MUST: All Organization parameters in billing endpoints MUST be marked with [BindNever] and injected via [InjectOrganization]. +- **R-BILLING-004** MUST: Organization entities MUST always be injected via [InjectOrganization] and never constructed from route parameters or request body data. +- **R-BILLING-005** SHOULD: Billing-specific authorization requirements SHOULD be placed in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements. +- **R-BILLING-006** SHOULD: Consistent parameter naming (organization) and binding attributes ([BindNever]) SHOULD be used across all billing endpoints to establish recognizable patterns during code review. + +### Verify + +```bash +# Check for billing controllers missing authorization attributes +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters are protected with [BindNever] +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- No billing endpoints construct Organization entities from route parameters or request body data + + +Claude Code MUST NOT skip or defer verification. All three verification commands MUST pass before accepting changes to billing controllers. Static analysis MUST detect missing authorization attributes and fail CI builds. Code review MUST verify the three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) on all organization billing endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-combine-declarative-1a73.md b/.actual/rules/cross-cutting-controllers-combine-declarative-1a73.md new file mode 100644 index 000000000000..013621c86c3c --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-combine-declarative-1a73.md @@ -0,0 +1,42 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Combine Declarative + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization enforcement, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, and service configuration registering authorization policies. + +### Rules + +- **R-AUTH-001** MAY: Controllers MAY combine declarative Authorize attributes with imperative IAuthorizationService calls for layered authorization. +- **R-AUTH-002** MUST: All resource-based authorization decisions MUST call AuthorizeAsync before granting access to protected resources. +- **R-AUTH-003** MUST: Authorization failures MUST throw NotFoundException to prevent information disclosure about resource existence. +- **R-AUTH-004** MUST: IAuthorizationService MUST be injected through constructor dependency injection in all controllers requiring authorization. +- **R-AUTH-005** MUST: Custom authorization requirements MUST be implemented by creating classes implementing IAuthorizationRequirement with corresponding handlers implementing AuthorizationHandler. +- **R-AUTH-006** MUST: Authorization policies MUST be registered in service configuration using services.AddAuthorization() in application startup. +- **R-AUTH-007** SHOULD: Public endpoints requiring no authorization SHOULD be explicitly marked with [AllowAnonymous] attribute and documented. +- **R-AUTH-008** SHOULD: Test environments SHOULD configure authorization policies separately from production configuration using environment-specific setup. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization registration +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count custom authorization handlers +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- Authorization failures consistently throw NotFoundException or appropriate HTTP status codes +- Custom authorization handlers are implemented for all authorization requirements + + +Claude Code MUST NOT skip or defer verification of authorization enforcement patterns. All protected endpoints MUST have explicit authorization checks. Missing authorization checks are treated as critical security defects. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-combine-multiple-46a6.md b/.actual/rules/cross-cutting-controllers-combine-multiple-46a6.md new file mode 100644 index 000000000000..76de2da3f998 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-combine-multiple-46a6.md @@ -0,0 +1,32 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Combine Multiple + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations requiring authorization enforcement across the Api and AdminConsole projects. + +### Rules + +- **R-AUTH-001** MAY: Controllers MAY combine multiple authorization checks by using both attribute-based authorization and programmatic ICurrentContext validation within action methods. + +### Verify + +```bash +# Count attribute-based authorization usage +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find unprotected controller actions +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions (e.g., *Requirement suffix) +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- Custom requirement classes are organized in dedicated namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) +- ICurrentContext is used only for supplementary runtime checks, not primary authorization + + +Claude Code MUST NOT skip or defer verification of authorization attributes on all protected controller actions. Static analysis failures block pull request merging until authorization attributes are added. Code review process requires explicit justification for any [AllowAnonymous] usage. Security team review is required for any new custom requirement classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-combine-multiple-8f6f.md b/.actual/rules/cross-cutting-controllers-combine-multiple-8f6f.md new file mode 100644 index 000000000000..3d3b4a70dd58 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-combine-multiple-8f6f.md @@ -0,0 +1,30 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controllers Combine Multiple + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces where authorization requirements must be declared via attributes on controller actions. + +### Rules + +- **R-AUTHZ-001** MAY: Controllers MAY combine multiple authorization attributes on a single action method when multiple authorization policies must be satisfied. + +### Verify + +```bash +# Scan for controller action methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization using statements +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either `[Authorize]` or `[AllowAnonymous]` attributes +- No controller action methods contain imperative authorization checks (`IAuthorizationService.AuthorizeAsync` calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI +- Multiple authorization attributes on a single action method are used only when multiple authorization policies must be satisfied simultaneously + + +Claude Code MUST NOT skip or defer verification. All controller actions must be audited for proper authorization attribute application before accepting changes to AdminConsole or Admin controller implementations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-handle-aggregate-730e.md b/.actual/rules/cross-cutting-controllers-handle-aggregate-730e.md new file mode 100644 index 000000000000..202aab80f04e --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-handle-aggregate-730e.md @@ -0,0 +1,36 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Controllers Handle Aggregate + +These rules are ALWAYS ACTIVE for all API controller classes that expose HTTP endpoints and coordinate command execution or query operations through service boundaries. + +### Rules + +- **R-CQSA-001** MUST: API controllers MUST handle aggregate exceptions for batch operations and domain-specific exceptions (e.g., SceneExecutionException) for single operations, returning structured error responses. +- **R-CQSA-002** MUST: All API controller action methods MUST use async Task signatures and await command/query interface methods rather than performing direct data access. +- **R-CQSA-003** MUST: Controllers MUST inject command/query interfaces (e.g., ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) via constructor dependency injection instead of directly accessing persistence layers. +- **R-CQSA-004** MUST: Controllers MUST NOT perform direct DbContext operations, SaveChanges calls, or Query/Execute operations on data access objects within controller class bodies. +- **R-CQSA-005** SHOULD: API endpoints SHOULD use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding. +- **R-CQSA-006** SHOULD: Controllers SHOULD implement structured logging at API boundary entry points using ILogger with semantic context (e.g., PlayIds, Template parameters) for operation traceability. + +### Verify + +```bash +# Verify all controller action methods use async Task pattern +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controllers (DbContext, SaveChanges, Query, Execute) +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files with async/await patterns +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access. +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments). +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar). +- Controllers inject command/query interfaces via constructor dependency injection and invoke them with await patterns. +- Error handling distinguishes between aggregate exceptions (batch operations) and domain-specific exceptions (single operations). + + +Clause Code MUST NOT skip or defer verification. All rules in this file are mandatory for API controller implementations. Violations block CI pipeline until resolved or explicitly exempted with architectural review and [ADR-AUTO-EXCEPTION] documentation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-handling-external-8ed8.md b/.actual/rules/cross-cutting-controllers-handling-external-8ed8.md new file mode 100644 index 000000000000..803949fe50ab --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-handling-external-8ed8.md @@ -0,0 +1,29 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Handling External + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes that invoke external services or handle sensitive resource operations after authorization checks. + +### Rules + +- **R-AUTH-LOG-001** SHOULD: Controllers handling external service calls within authorized contexts SHOULD log both the failure and the partial success state to support audit and rollback analysis. + +### Verify + +```bash +# Check for [Authorize] attributes without ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters in controller files +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in logging statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + + +Clause Code MUST NOT skip or defer verification. All controllers with [Authorize] attributes or custom authorization requirements must inject ILogger and log authorization-related failures with structured context parameters. Pull requests with authorized endpoints lacking structured logging are blocked until logging is added. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-have-class-100f.md b/.actual/rules/cross-cutting-controllers-have-class-100f.md new file mode 100644 index 000000000000..f2c465a1ba18 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-have-class-100f.md @@ -0,0 +1,30 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Controllers Have Class + +These rules are ALWAYS ACTIVE for all API controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes and their HTTP action methods. + +### Rules + +- **R-CTRL-001** MUST: All API controllers MUST have a class-level [Authorize] attribute unless explicitly exempted by documented exception. + +### Verify + +```bash +# Check for AssertAllHttpMethodsHaveAuthorization invocations in test files +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run controller authorization tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes on controller classes +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- No HTTP action methods lack authorization attributes unless marked with [AllowAnonymous] and documented as exceptions + + +Claude Code MUST NOT skip or defer verification. Authorization attribute presence MUST be validated via unit test execution before accepting controller code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-aa26.md b/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-aa26.md new file mode 100644 index 000000000000..cdf77789cb45 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-aa26.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Controllers Inject Iauthorizationservice + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST inject IAuthorizationService as a constructor dependency and store it as a private readonly field. + +### Verify + +```bash +# Count IAuthorizationService injections in controller files +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controller files +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controller files +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- IAuthorizationService is injected as a private readonly field in controller constructors +- Authorization checks precede all protected operations in controller actions + + +Claude Code MUST NOT skip or defer verification. All protected controller actions must be verified to contain authorization checks before performing operations on protected resources. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-d74b.md b/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-d74b.md new file mode 100644 index 000000000000..aa00daddcf47 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-inject-iauthorizationservice-d74b.md @@ -0,0 +1,42 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Inject Iauthorizationservice + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization enforcement, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, service configuration in Startup or Program.cs registering authorization policies, and integration test factories configuring test authentication and authorization schemes. + +### Rules + +- **R-AUTH-001** MUST: Controllers MUST inject IAuthorizationService through constructor dependency injection. +- **R-AUTH-002** MUST: All resource-based authorization decisions MUST call AuthorizeAsync before granting access. +- **R-AUTH-003** MUST: Authorization failures MUST be handled by throwing NotFoundException to prevent information disclosure about resource existence. +- **R-AUTH-004** MUST: Authorization policies MUST be registered in service configuration using AddAuthorization(). +- **R-AUTH-005** MUST: Public endpoints requiring no authorization MUST be explicitly marked with [AllowAnonymous] attribute and documented. +- **R-AUTH-006** SHOULD: Custom authorization requirements SHOULD be implemented by creating classes implementing IAuthorizationRequirement with corresponding handlers implementing AuthorizationHandler. +- **R-AUTH-007** SHOULD: Test environments SHOULD configure authorization policies separately from production configuration to prevent test policies from being deployed to production. + +### Verify + +```bash +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization is registered +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count custom authorization handlers +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization failures are handled by throwing NotFoundException +- Authorization policies are registered in service configuration with AddAuthorization +- Public endpoints are explicitly marked with [AllowAnonymous] attribute +- Test projects configure authorization policies separately from production configuration +- Custom authorization requirements are implemented with corresponding handlers + + +Claude Code MUST NOT skip or defer verification of these authorization rules. All controllers requiring authorization MUST inject IAuthorizationService and call AuthorizeAsync for resource-based decisions. Missing authorization checks are security vulnerabilities and MUST be remediated immediately. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-log-operation-b1e7.md b/.actual/rules/cross-cutting-controllers-log-operation-b1e7.md new file mode 100644 index 000000000000..521ee0c926ea --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-log-operation-b1e7.md @@ -0,0 +1,30 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Controllers Log Operation + +These rules are ALWAYS ACTIVE for all C# controller classes in the Bit.SeederApi service that expose HTTP endpoints through ASP.NET Core MVC attributes. + +### Rules + +- **R-CQSA-001** SHOULD: Controllers SHOULD log operation context at API boundaries using structured logging with relevant identifiers (PlayIds, Template, OlderThan). + +### Verify + +```bash +# Verify all API controller action methods use async Task signatures +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controller classes (DbContext, SaveChanges, Query, Execute) +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files using async/await patterns with interface method invocations +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use `async Task` signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) +- Structured logging statements are present at API boundary entry points using ILogger with semantic context (PlayIds, Template parameters) + + +Claude Code MUST NOT skip or defer verification. All controller files must be scanned for compliance with command-query separation and async execution patterns. Violations must be flagged for architectural review before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-log-successful-0929.md b/.actual/rules/cross-cutting-controllers-log-successful-0929.md new file mode 100644 index 000000000000..a55938286293 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-log-successful-0929.md @@ -0,0 +1,29 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Log Successful + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes, particularly ProvidersController and HomeController, and all controller actions that invoke external services after authorization checks. + +### Rules + +- **R-AUTH-LOG-001** MAY: Controllers MAY log successful authorization decisions at Debug or Trace level for detailed audit trails in non-production environments. + +### Verify + +```bash +# Find all controllers with [Authorize] that lack ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Find LogError calls without structured parameters (missing curly braces) +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Find log statements containing sensitive parameter names +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + + +Clause Code MUST NOT skip or defer verification. All three verify commands must pass before accepting changes to authorized controller endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-managing-related-25e3.md b/.actual/rules/cross-cutting-controllers-managing-related-25e3.md new file mode 100644 index 000000000000..5777d17818c4 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-managing-related-25e3.md @@ -0,0 +1,30 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Controllers Managing Related + +These rules are ALWAYS ACTIVE for all internal API endpoint implementations in the AdminConsole and Admin controllers requiring authorization enforcement to protect organization-level resources and administrative functions. + +### Rules + +- **R-AUTH-001** SHOULD: Controllers managing related resources SHOULD apply consistent authorization requirements across all CRUD operations (GET, POST, PUT, DELETE) for that resource type. + +### Verify + +```bash +# Count authorization attributes on internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Verify public action methods have authorization attributes +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes +- Public endpoints are explicitly marked with [AllowAnonymous] attribute with security rationale documented in code comments + + +Claude Code MUST NOT skip or defer verification. All internal API endpoints must have authorization attributes applied before code review approval. CI pipeline MUST fail if security tests detect endpoints without required authorization attributes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-separate-read-1915.md b/.actual/rules/cross-cutting-controllers-separate-read-1915.md new file mode 100644 index 000000000000..caad253ae2cb --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-separate-read-1915.md @@ -0,0 +1,30 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Separate Read + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically controllers in `Bit.Api.AdminConsole.Controllers` handling OrganizationUser entities and collection-access modifications. + +### Rules + +- **R-AUTHZ-001** SHOULD: Controllers SHOULD separate read-only collection access from editable collection access when merging user permissions to preserve collections the current user cannot modify. + +### Verify + +```bash +# Verify IAuthorizationService is injected in organization user controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called for bulk collection operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in `Bit.Api.AdminConsole.Controllers` managing organization users inject `IAuthorizationService` as a private readonly field +- All endpoints modifying collection access call `AuthorizeAsync` with appropriate requirements before persistence operations +- Authorization failures consistently throw `NotFoundException` to prevent enumeration attacks +- Read-only and editable collections are separated during user permission merges + + +Claude Code MUST NOT skip or defer verification of these authorization rules. Authorization gaps represent critical security vulnerabilities and MUST be caught during review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-throw-notfoundexception-cdc8.md b/.actual/rules/cross-cutting-controllers-throw-notfoundexception-cdc8.md new file mode 100644 index 000000000000..21eef622e95f --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-throw-notfoundexception-cdc8.md @@ -0,0 +1,34 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Throw Notfoundexception + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization enforcement, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, service configuration in Startup or Program.cs registering authorization policies, and integration test factories configuring test authentication and authorization schemes. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST throw NotFoundException when authorization fails to prevent information disclosure about resource existence. + +### Verify + +```bash +# Verify IAuthorizationService injection in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Verify AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization registration +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Verify authorization handler implementations +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- NotFoundException is thrown on authorization failure to prevent information disclosure + + +Claude Code MUST NOT skip or defer verification. All protected endpoints MUST enforce authorization using IAuthorizationService and throw NotFoundException on authorization failures. Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-allowanonymous-2156.md b/.actual/rules/cross-cutting-controllers-use-allowanonymous-2156.md new file mode 100644 index 000000000000..c0f2b9cb2465 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-allowanonymous-2156.md @@ -0,0 +1,30 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controllers Use Allowanonymous + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controller action methods in the Api.AdminConsole and Admin namespaces. + +### Rules + +- **R-AUTHZ-001** SHOULD: Controllers SHOULD use AllowAnonymous attribute explicitly for public endpoints to document intentional lack of authorization. + +### Verify + +```bash +# Scan for controller action methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization using statements +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either `[Authorize]` or `[AllowAnonymous]` attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI +- Public endpoints are explicitly marked with `[AllowAnonymous]` to document intentional lack of authorization + + +Claude Code MUST NOT skip or defer verification. All controller actions must be audited for proper authorization attribute application before accepting changes to AdminConsole or Admin controller files. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-authorize-1b71.md b/.actual/rules/cross-cutting-controllers-use-authorize-1b71.md new file mode 100644 index 000000000000..7ad825ccc670 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-authorize-1b71.md @@ -0,0 +1,38 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Controllers Use Authorize + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects that expose HTTP action methods accessing organizational or user-scoped resources. + +### Rules + +- **R-AUTH-001** SHOULD: Controllers SHOULD use [Authorize("Application")] at the class level for base authentication requirements, with action-specific attributes for fine-grained authorization. +- **R-AUTH-002** MUST: All controller action methods returning IResult or IActionResult MUST have either [Authorize], [Authorize], or [AllowAnonymous] attributes. +- **R-AUTH-003** MUST: Custom authorization requirement classes MUST implement IAuthorizationRequirement and have corresponding registered handler implementations. +- **R-AUTH-004** SHOULD: Custom authorization requirements SHOULD be created by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations. +- **R-AUTH-005** SHOULD: Authorization handlers SHOULD be registered in the dependency injection container during application startup (typically in Program.cs or Startup.cs). +- **R-AUTH-006** MAY: For actions requiring multiple authorization checks, developers MAY apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions. +- **R-AUTH-007** MUST: [AllowAnonymous] usage MUST be documented with security rationale in code comments and justified in pull request descriptions. +- **R-AUTH-008** MUST: Public endpoints for invite token validation or version checking MAY require anonymous access only when explicitly documented as exceptions. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify all custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All [AllowAnonymous] usage is documented with security rationale and approved by security team + + +Claude Code MUST NOT skip or defer verification. All controller actions MUST be decorated with appropriate authorization attributes before code is considered compliant. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-base-de8d.md b/.actual/rules/cross-cutting-controllers-use-base-de8d.md new file mode 100644 index 000000000000..e9dbd41ca0fa --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-base-de8d.md @@ -0,0 +1,38 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Controllers Use Base + +These rules are ALWAYS ACTIVE for all API controller endpoints requiring authorization in the AdminConsole API surface, specifically all controllers in the Bit.Api.AdminConsole.Controllers namespace and all HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST use the base Authorize attribute with "Application" parameter at the class level to enforce application-level authentication before requirement-specific authorization. +- **R-AUTHZ-002** MUST: All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests MUST have either a [Authorize] attribute or an explicit [AllowAnonymous] attribute. +- **R-AUTHZ-003** MUST: Authorization requirement classes MUST be defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and MUST follow the Requirement naming suffix convention (e.g., ManageUsersRequirement, ManagePoliciesRequirement). +- **R-AUTHZ-004** MUST: Controller methods MUST NOT use string-based Authorize(Policy = "...") attributes for authorization requirements; use generic Authorize attributes instead. +- **R-AUTHZ-005** SHOULD: Complex authorization logic that depends on request parameters SHOULD be supplemented with imperative checks using ICurrentContext or authorization services, with clear documentation of the rationale. +- **R-AUTHZ-006** SHOULD: Public endpoints that intentionally bypass authorization SHOULD be explicitly marked with [AllowAnonymous] to facilitate security audits. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes defined in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +# Verify no string-based policy authorization in AdminConsole controllers +grep -r "Authorize(Policy" src/Api/AdminConsole/Controllers/ | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements +- The count of public async methods without authorization attributes is zero (excluding health check and diagnostic endpoints) + + +Claude Code MUST NOT skip or defer verification. Static analysis during CI pipeline using custom Roslyn analyzers or linting rules is mandatory. Code review must verify authorization attributes on all new endpoints. Security-focused integration tests must verify authorization enforcement for each endpoint. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-iauthorizationservice-e782.md b/.actual/rules/cross-cutting-controllers-use-iauthorizationservice-e782.md new file mode 100644 index 000000000000..2b2b8d6fb092 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-iauthorizationservice-e782.md @@ -0,0 +1,38 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Controllers Use Iauthorizationservice + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, and for operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** MUST: Controllers MUST use IAuthorizationService.AuthorizeAsync with typed requirements rather than role-based checks for authorization decisions. +- **R-AUTHZ-002** MUST: Authorization checks using IAuthorizationService MUST occur before domain validation logic in all organization user management endpoints. +- **R-AUTHZ-003** MUST: Failed authorization checks MUST throw NotFoundException (not UnauthorizedException or ForbiddenException) to prevent information disclosure about resource existence. +- **R-AUTHZ-004** MUST: For operations modifying collection access, all affected collections MUST be loaded and verified with ModifyUserAccess authorization before applying changes. +- **R-AUTHZ-005** MUST: Collection access modification operations MUST verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes. +- **R-AUTHZ-006** MUST: Organization abilities (AllowAdminAccessToAllCollectionItems) MUST be checked before allowing self-modification operations that could escalate privileges. +- **R-AUTHZ-007** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-AUTHZ-008** SHOULD: Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections. + +### Verify + +```bash +# Count authorization checks using BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Count NotFoundException throws paired with AuthorizeAsync in OrganizationUsersController +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- IAuthorizationService is injected into all relevant controllers and used for authorization decisions + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for organization user management controllers. Authorization checks MUST precede domain validation in all cases. Code review and static analysis verification is required before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-icurrentcontext-7929.md b/.actual/rules/cross-cutting-controllers-use-icurrentcontext-7929.md new file mode 100644 index 000000000000..ef86040143e0 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-icurrentcontext-7929.md @@ -0,0 +1,31 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Use Icurrentcontext + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers in the Api and AdminConsole projects that access protected organizational or user resources. + +### Rules + +- **R-AUTH-001** SHOULD: Controllers SHOULD use ICurrentContext for additional runtime authorization checks when attribute-based authorization alone is insufficient. + +### Verify + +```bash +# Count generic [Authorize] attributes across controller files +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Identify controller actions without authorization attributes +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions (e.g., *Requirement suffix) +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- ICurrentContext is used only for supplementary runtime checks, not primary authorization enforcement + + +Claude Code MUST NOT skip or defer verification. Static analysis failures block pull request merging until authorization attributes are added. Code review process requires explicit justification for any [AllowAnonymous] usage. Security team review is required for any new custom requirement classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-controllers-use-multiple-79e8.md b/.actual/rules/cross-cutting-controllers-use-multiple-79e8.md new file mode 100644 index 000000000000..ce0db62a8105 --- /dev/null +++ b/.actual/rules/cross-cutting-controllers-use-multiple-79e8.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Use Multiple + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically all controllers in `Bit.Api.AdminConsole.Controllers` handling OrganizationUser entities and user-collection associations. + +### Rules + +- **R-AUTHZ-001** MAY: Controllers MAY use multiple authorization requirements in sequence (e.g., ManageUsersRequirement followed by resource-specific checks) for layered authorization of organization user operations. + +### Verify + +```bash +# Verify IAuthorizationService is injected in organization user controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called for collection modification operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException to prevent enumeration +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in `Bit.Api.AdminConsole.Controllers` managing organization users inject `IAuthorizationService` as a private readonly field +- All endpoints modifying collection access call `AuthorizeAsync` with appropriate requirements (ManageUsersRequirement, resource-specific checks) before persistence operations +- Authorization failures consistently throw `NotFoundException()` without additional details to prevent enumeration attacks +- Self-modification scenarios check `organizationAbility.AllowAdminAccessToAllCollectionItems` before allowing collection/group additions +- Editable and read-only collections are separated by authorization checks during updates + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST execute successfully. Authorization checks are security-critical and must be present before any collection modification persists to the database. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cross-language-data-2955.md b/.actual/rules/cross-cutting-cross-language-data-2955.md new file mode 100644 index 000000000000..e39967456681 --- /dev/null +++ b/.actual/rules/cross-cutting-cross-language-data-2955.md @@ -0,0 +1,35 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Cross Language Data + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, primary DatabaseContext class managing application-wide entity collections, cross-language data structure definitions requiring FFI bindings (Rust SDK), and entity types representing persistent domain models. + +### Rules + +- **R-DBSET-001** SHOULD: Cross-language data structures (e.g., Rust FFI bindings) SHOULD use explicit type declarations with standard library types (std::ffi::CString, std::collections::HashSet) for interoperability. +- **R-DBSET-002** MUST: All persistent entity types MUST be exposed as public DbSet properties in DatabaseContext with plural naming conventions. +- **R-DBSET-003** SHOULD: Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities). +- **R-DBSET-004** SHOULD: Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic. +- **R-DBSET-005** SHOULD: For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings and document mapping conventions. +- **R-DBSET-006** MUST: New entity types added to the codebase MUST include corresponding DbSet property declarations in DatabaseContext following the pattern 'public DbSet EntityTypes { get; set; }'. + +### Verify + +```bash +# Count DbSet declarations in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet declarations follow naming pattern +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting +- Cross-language data structures use explicit type declarations with standard library types for interoperability + + +Claude Code MUST NOT skip or defer verification. Pull requests adding entity types without corresponding DbSet properties are blocked by code review. Build failures from missing entity registrations halt CI pipeline until resolved. Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cross-language-ffi-ab20.md b/.actual/rules/cross-cutting-cross-language-ffi-ab20.md new file mode 100644 index 000000000000..cbff860bd092 --- /dev/null +++ b/.actual/rules/cross-cutting-cross-language-ffi-ab20.md @@ -0,0 +1,34 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Cross Language Ffi + +These rules are ALWAYS ACTIVE for all HTTP client implementations in cross-language FFI boundaries and external service integrations across Rust and C# codebases. + +### Rules + +- **R-FFI-001** MUST: Cross-language FFI boundaries involving external HTTP communication MUST use safe string marshaling patterns (CStr, CString) with proper memory management. +- **R-FFI-002** MUST: All production services register HTTP clients through dependency injection (AddHttpClient in .NET, equivalent patterns in Rust) rather than direct instantiation. +- **R-FFI-003** MUST: Configure base addresses, default headers, timeout policies, and retry logic at HTTP client registration time, not per-request. +- **R-FFI-004** SHOULD: Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries. +- **R-FFI-005** SHOULD: For rate-limited external APIs, integrate with distributed rate limiting infrastructure (Redis-backed counters) to coordinate limits across service instances. + +### Verify + +```bash +# Count AddHttpClient registrations in .NET services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Count direct HttpClient instantiations outside tests (should be 0 in production) +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Count safe FFI string marshaling imports in Rust +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients +- No direct HttpClient instantiation patterns detected in production code paths + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns, code review checklists for HTTP client registration, and integration test validation are mandatory before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-components-cipher-bbc8.md b/.actual/rules/cross-cutting-cryptographic-components-cipher-bbc8.md new file mode 100644 index 000000000000..2ebb502ce16a --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-components-cipher-bbc8.md @@ -0,0 +1,37 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Components Cipher + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions exposed through C FFI boundaries, memory management functions for C-allocated strings and cryptographic keys, and input validation for cipher and RSA key operations in the Rust SDK. + +### Rules + +- **R-CRYPTO-001** SHOULD: Cryptographic components (cipher, rsa_keys) SHOULD have dedicated test mocks to validate behavior in isolation. +- **R-CRYPTO-002** MUST: All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it. +- **R-CRYPTO-003** MUST: Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead. +- **R-CRYPTO-004** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-CRYPTO-005** MUST: Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns. + +### Verify + +```bash +# Verify FFI functions use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in public API +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- All FFI boundary functions have paired allocation/deallocation verified in code review +- No memory leaks are detected in CI using valgrind or similar tools on FFI integration tests +- No panics occur at FFI boundaries; all error conditions return error codes +- Test mocks for cipher and rsa_keys components are present and cover edge cases + + +Claude Code MUST NOT skip or defer verification. All FFI functions without paired deallocation functions MUST be rejected in code review. Memory leaks detected in CI MUST block merge until resolved. Panics at FFI boundaries MUST be converted to error returns before production deployment. Exceptions for FFI patterns MUST be reviewed by security team and SDK maintainers, documented in code comments with rationale and approval record. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-key-generation-b56a.md b/.actual/rules/cross-cutting-cryptographic-key-generation-b56a.md new file mode 100644 index 000000000000..f3f768995e60 --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-key-generation-b56a.md @@ -0,0 +1,37 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Key Generation + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions exposed through FFI boundaries in the Rust SDK, specifically targeting util/RustSdk/rust/src/lib.rs and related FFI boundary implementations that allocate or manipulate cryptographic material. + +### Rules + +- **R-CRYPTO-FFI-001** MUST: All cryptographic key generation functions exposed through FFI MUST use c_char pointers with explicit CString/CStr conversions for string parameters. +- **R-CRYPTO-FFI-002** MUST: All new FFI functions that allocate memory MUST provide a corresponding free_* function and document the caller's responsibility to invoke it. +- **R-CRYPTO-FFI-003** MUST: Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead. +- **R-CRYPTO-FFI-004** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-CRYPTO-FFI-005** SHOULD: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production. +- **R-CRYPTO-FFI-006** SHOULD: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns. + +### Verify + +```bash +# Verify all public FFI functions for key generation use c_char pointers +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in public API +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- All FFI boundary functions have paired allocation/deallocation verified in code review +- No memory leaks are detected in CI using valgrind or similar tools on FFI integration tests +- No panics occur at FFI boundaries; all error conditions return error codes + + +Claude Code MUST NOT skip or defer verification. All FFI functions must pass code review confirming paired allocation/deallocation, static analysis for error handling around CString conversions, and CI memory leak detection before merge. Violations must be resolved or approved by security team and SDK maintainers. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-key-generation-fbc0.md b/.actual/rules/cross-cutting-cryptographic-key-generation-fbc0.md new file mode 100644 index 000000000000..58e0a4749d41 --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-key-generation-fbc0.md @@ -0,0 +1,37 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Cryptographic Key Generation + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that expose cryptographic key generation and management functions to C callers, including all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-CRYPTO-FFI-001** MUST: Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) MUST validate all input strings before processing. +- **R-CRYPTO-FFI-002** MUST: All public FFI functions returning strings MUST use CString::into_raw() to transfer ownership and document the requirement to call free_c_string. +- **R-CRYPTO-FFI-003** MUST: The free_c_string function MUST use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup. +- **R-CRYPTO-FFI-004** MUST: Input validation MUST check for null pointers using .is_null() before dereferencing c_char pointers from C. +- **R-CRYPTO-FFI-005** SHOULD: Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns. +- **R-CRYPTO-FFI-006** SHOULD: Document the memory ownership contract in header files and API documentation, including examples of correct usage. + +### Verify + +```bash +# Count CString ownership transfer patterns +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No FFI functions return raw pointers without corresponding deallocation functions +- Memory sanitizer tests (AddressSanitizer, LeakSanitizer) pass in CI pipeline + + +Clause Code MUST NOT skip or defer verification. Code review MUST check CString usage patterns in FFI functions. Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) MUST pass. Integration tests with memory sanitizers MUST pass before merge. Security team escalation is required for violations in cryptographic key handling code. Exceptions for static string literals (EXC-001) require security team approval and documentation in code comments. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-key-material-893a.md b/.actual/rules/cross-cutting-cryptographic-key-material-893a.md new file mode 100644 index 000000000000..0caeaae2208a --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-key-material-893a.md @@ -0,0 +1,37 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Cryptographic Key Material + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers, including all public FFI functions in `util/RustSdk/rust/src/lib.rs`, modules handling RSA key material via `util/RustSdk/rust/src/rsa_keys.rs`, functions coordinating with `bitwarden_crypto::SymmetricCryptoKey` or cipher operations, and memory management functions like `free_c_string`. + +### Rules + +- **R-FFI-CRYPTO-001** MUST: Cryptographic key material received via FFI MUST be validated for format correctness (e.g., PEM structure) before passing to bitwarden_crypto operations. +- **R-FFI-CRYPTO-002** MUST: Wrap all `c_char` pointer parameters with `unsafe { CStr::from_ptr(ptr) }` and handle the Result for UTF-8 validation before dereferencing. +- **R-FFI-CRYPTO-003** MUST: Use `CString::new(rust_string)?.into_raw()` for outbound strings and track returned pointers for cleanup via `free_c_string`. +- **R-FFI-CRYPTO-004** MUST: Document ownership semantics in FFI function comments, specifying whether caller or callee owns memory and when `free_c_string` must be called. +- **R-FFI-CRYPTO-005** SHOULD: Maintain fake key constants (`_FAKE_RSA_KEY_N`) in test modules, ensuring they match production PEM format including BEGIN/END markers. +- **R-FFI-CRYPTO-006** SHOULD: Consider using `std::collections::HashSet` to track allocated `CString` pointers and detect double-free attempts in debug builds. +- **R-FFI-CRYPTO-007** MAY: Skip validation in performance-critical inner loops where input has been pre-validated at the FFI entry point (EXC-001), provided pre-validation is documented and safety argument provided. + +### Verify + +```bash +# Check that all public FFI functions accepting c_char pointers include CStr validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify at least 5 fake RSA key fixtures exist for validating cryptographic input handling +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Confirm RSA key validation tests pass +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting `c_char` pointers include `CStr::from_ptr` validation before dereferencing. +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling. +- Cargo test suite for `rsa_keys` module passes, confirming validation logic handles both valid and invalid inputs. +- Ownership semantics are documented in FFI function comments. +- No FFI functions with `c_char` parameters lack corresponding CStr validation patterns. + + +Clause Code MUST NOT skip or defer verification. CI pipeline MUST run grep-based checks for CStr usage patterns in FFI functions. Code review MUST require security team sign-off on new FFI functions. Cargo test suite MUST include negative test cases with malformed input. CI build MUST fail if FFI functions lack CStr validation patterns. Security team MUST block PR merge until validation is added and tested. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-key-types-93ca.md b/.actual/rules/cross-cutting-cryptographic-key-types-93ca.md new file mode 100644 index 000000000000..364fbe2cecc2 --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-key-types-93ca.md @@ -0,0 +1,38 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Cryptographic Key Types + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in `util/RustSdk/rust/src/lib.rs` that handle cryptographic key material, including public key generation APIs, cipher and RSA key data structures exposed across FFI boundaries, and test infrastructure requiring mock implementations of cryptographic primitives. + +### Rules + +- **R-CRYPTO-FFI-001** MUST: All cryptographic key types (cipher, rsa_keys, SymmetricCryptoKey) MUST be modeled as distinct data structures with explicit FFI-safe representations using std::ffi types (c_char, CStr, CString). +- **R-CRYPTO-FFI-002** MUST: Use `#[repr(C)]` attribute on all data structures crossing FFI boundaries to ensure stable memory layout. +- **R-CRYPTO-FFI-003** MUST: Wrap all `CStr::from_ptr` calls in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-CRYPTO-FFI-004** MUST: Implement defensive validation using `CStr::from_ptr` safety checks and return error codes to C callers instead of panicking. +- **R-CRYPTO-FFI-005** MUST: Provide memory management functions (free_c_string) for all FFI-allocated strings and document ownership semantics in FFI function comments. +- **R-CRYPTO-FFI-006** SHOULD: Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations. +- **R-CRYPTO-FFI-007** SHOULD: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly. +- **R-CRYPTO-FFI-008** SHOULD: Monitor RSA_POOL contention metrics; consider sharded pool design or per-thread key caches if contention is observed. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Run cryptographic tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 +``` + +**Accept when:** +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings +- All data structures crossing FFI boundaries use `#[repr(C)]` attribute +- All `CStr::from_ptr` calls include null pointer checks and UTF-8 validation + + +Claude Code MUST NOT skip or defer verification. CI build fails if FFI functions lack required validation or memory management functions. Pull requests adding new FFI entry points require security team approval. Runtime panics in FFI code trigger incident review and post-mortem analysis. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-operations-cipher-f6f6.md b/.actual/rules/cross-cutting-cryptographic-operations-cipher-f6f6.md new file mode 100644 index 000000000000..8ce228fc02b6 --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-operations-cipher-f6f6.md @@ -0,0 +1,50 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Cryptographic Operations Cipher + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in `util/RustSdk/rust/src/lib.rs` that handle cryptographic key material, public key generation APIs, and cipher/RSA key data structures exposed across FFI boundaries. + +### Rules + +- **R-CRYPTO-001** SHOULD: Cryptographic operations (cipher, rsa_keys) SHOULD provide mock implementations or test doubles to enable unit testing without real key material. +- **R-CRYPTO-002** MUST: Use `#[repr(C)]` attribute on all data structures crossing FFI boundaries to ensure stable memory layout. +- **R-CRYPTO-003** MUST: Wrap all `CStr::from_ptr` calls in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-CRYPTO-004** MUST: All public FFI functions handling key material use `std::ffi` types (c_char, CStr, CString) with explicit validation. +- **R-CRYPTO-005** MUST: Provide memory management functions (free_c_string) for all FFI-allocated strings and document ownership semantics in function comments. +- **R-CRYPTO-006** SHOULD: Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations. +- **R-CRYPTO-007** SHOULD: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Run tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 + +# Verify #[repr(C)] on FFI-crossing structures +grep -B1 'pub struct' util/RustSdk/rust/src/lib.rs | grep -c 'repr(C)' + +# Verify CStr validation patterns +grep -c 'CStr::from_ptr' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions handling key material use `std::ffi` types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings +- All data structures crossing FFI boundaries use `#[repr(C)]` attribute +- CStr::from_ptr calls include null pointer checks and UTF-8 validation +- Both unit tests (with mocks) and integration tests (with real crypto) pass in CI pipeline + + +Verified by: Automated code review checks for FFI functions missing input validation or proper error handling. +Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness. +Verified by: Security team audits FFI boundary code during quarterly security reviews. +Violation handling: CI build fails if FFI functions lack required validation or memory management functions. +Violation handling: Pull requests adding new FFI entry points require security team approval. +Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis. +Claude Code MUST NOT skip or defer verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-operations-involving-e4ca.md b/.actual/rules/cross-cutting-cryptographic-operations-involving-e4ca.md new file mode 100644 index 000000000000..ce6f1a52bcf9 --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-operations-involving-e4ca.md @@ -0,0 +1,38 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Operations Involving + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions and FFI boundary operations in the Rust SDK that involve SymmetricCryptoKey and RSA key material, specifically targeting util/RustSdk/rust/src/lib.rs and related FFI boundary functions. + +### Rules + +- **R-CRYPTO-FFI-001** MUST: Cryptographic operations involving SymmetricCryptoKey and RSA key material MUST validate inputs before processing. +- **R-CRYPTO-FFI-002** MUST: All public FFI functions that allocate memory for cryptographic material MUST provide a corresponding free_* function and document the caller's responsibility to invoke it. +- **R-CRYPTO-FFI-003** MUST: Use std::ffi types (c_char, CStr, CString) for all FFI boundary string handling in cryptographic operations. +- **R-CRYPTO-FFI-004** MUST: Wrap CString conversions with std::panic::catch_unwind to prevent panics from crossing FFI boundaries; return error codes instead. +- **R-CRYPTO-FFI-005** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-CRYPTO-FFI-006** SHOULD: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks to prevent mock divergence from production behavior. +- **R-CRYPTO-FFI-007** SHOULD: Document memory management requirements clearly in API documentation with examples showing correct allocation/deallocation patterns. + +### Verify + +```bash +# Verify FFI functions use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in public API +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- Input validation is performed on all cryptographic operation parameters before processing +- CString conversions are wrapped with error handling rather than allowing panics +- All FFI functions allocating cryptographic material have paired deallocation functions + + +Claude Code MUST NOT skip or defer verification. All FFI boundary functions must be reviewed for memory safety, input validation, and proper error handling before code is accepted. Memory leaks detected in CI must block merge. Panics at FFI boundaries must be converted to error returns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cryptographic-types-cipher-8303.md b/.actual/rules/cross-cutting-cryptographic-types-cipher-8303.md new file mode 100644 index 000000000000..ea24b512ed4e --- /dev/null +++ b/.actual/rules/cross-cutting-cryptographic-types-cipher-8303.md @@ -0,0 +1,38 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Cryptographic Types Cipher + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that expose cryptographic key generation and management functions to C consumers, including all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-CRYPTO-FFI-001** MUST: Cryptographic types (cipher, SymmetricCryptoKey, RSA_POOL) MUST be encapsulated behind opaque pointers when exposed through FFI. +- **R-CRYPTO-FFI-002** MUST: All public FFI functions returning strings MUST use `CString::into_raw()` to transfer ownership and document the requirement to call `free_c_string`. +- **R-CRYPTO-FFI-003** MUST: A `free_c_string` function MUST exist and be exported in the public API to reclaim ownership using `CString::from_raw()` before deallocation. +- **R-CRYPTO-FFI-004** MUST: Input validation MUST check for null pointers using `.is_null()` before dereferencing `c_char` pointers from C. +- **R-CRYPTO-FFI-005** SHOULD: FFI functions SHOULD be wrapped in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns. +- **R-CRYPTO-FFI-006** SHOULD: Documentation SHOULD include examples of correct string ownership transfer and deallocation for all FFI functions. +- **R-CRYPTO-FFI-007** MAY: Static string literals that do not require deallocation MAY be exempted from ownership transfer requirements (EXC-001). + +### Verify + +```bash +# Count CString usage patterns in FFI functions +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use `CString::into_raw()` and document `free_c_string` requirement +- A `free_c_string` function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing `c_char` parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No use-after-free or double-free vulnerabilities are detected by memory sanitizers +- Clippy FFI safety lints pass without warnings + + +Clause Code MUST NOT skip or defer verification. All FFI functions handling cryptographic key material MUST pass memory sanitizer checks and code review before merge. Security team escalation is required for any violations in cryptographic key handling code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-csbindgen-configuration-specify-8c53.md b/.actual/rules/cross-cutting-csbindgen-configuration-specify-8c53.md new file mode 100644 index 000000000000..9d0fe09b256d --- /dev/null +++ b/.actual/rules/cross-cutting-csbindgen-configuration-specify-8c53.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Csbindgen Configuration Specify + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs) responsible for generating language bindings, test fixtures and mock data used for cryptographic operation testing, and the public API surface exposed through FFI to managed C# code. + +### Rules + +- **R-CSBINDGEN-001** SHOULD: The csbindgen configuration SHOULD specify the native library name (csharp_dll_name) to match the compiled Rust artifact. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Verify test fixtures use clear naming conventions +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated C# bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile. Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions. Verified by: Static analysis tools scan for usage of test constants in non-test production code paths. Claude Code MUST NOT skip or defer verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cstr-conversions-performed-7c7f.md b/.actual/rules/cross-cutting-cstr-conversions-performed-7c7f.md new file mode 100644 index 000000000000..4f45e622bef1 --- /dev/null +++ b/.actual/rules/cross-cutting-cstr-conversions-performed-7c7f.md @@ -0,0 +1,35 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Cstr Conversions Performed + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, and string marshaling code in lib.rs and cipher.rs modules. + +### Rules + +- **R-FFI-001** MUST: CStr conversions MUST be performed within unsafe blocks with explicit null pointer checks or error handling for invalid UTF-8 sequences. +- **R-FFI-002** MUST: Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing. +- **R-FFI-003** MUST: Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop. +- **R-FFI-004** MUST: Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing. +- **R-FFI-005** SHOULD: Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called. +- **R-FFI-006** SHOULD: Add FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators. + +### Verify + +```bash +# Verify all CStr::from_ptr conversions are within unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" +``` + +**Accept when:** +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + + +Claude Code MUST NOT skip or defer verification. All FFI string conversions must be validated before accepting changes to cryptographic FFI boundaries. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-cstr-string-conversions-205a.md b/.actual/rules/cross-cutting-cstr-string-conversions-205a.md new file mode 100644 index 000000000000..061c01096b6d --- /dev/null +++ b/.actual/rules/cross-cutting-cstr-string-conversions-205a.md @@ -0,0 +1,36 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Cstr String Conversions + +These rules are ALWAYS ACTIVE for all public `extern "C"` functions in util/RustSdk/rust/src/ that accept C-style string pointers (c_char) from external callers, and for FFI helper functions that process C string inputs before cryptographic operations. + +### Rules + +- **R-FFI-001** MUST: CStr to String conversions MUST handle UTF-8 validation errors explicitly and return appropriate error codes to C callers. +- **R-FFI-002** MUST: All c_char pointer parameters MUST be wrapped in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers. +- **R-FFI-003** MUST: Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-004** MUST: For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks. +- **R-FFI-005** MUST: Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior. +- **R-FFI-006** MUST: Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files. + +### Verify + +```bash +# Verify all extern "C" functions accepting c_char pointers use CStr::from_ptr +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify count of CString::into_raw matches string-returning FFI functions +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi +``` + +**Accept when:** +- All public `extern "C"` functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data. +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function. +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling. +- All FFI function comments document string encoding requirements (UTF-8, null-terminated). +- No panics occur on invalid UTF-8 input; instead, error codes are returned to C callers. + + +Claude Code MUST NOT skip or defer verification. All R-FFI-### rules are mandatory for FFI boundary code. Violations must be caught by CI checks using grep patterns and code review before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-authorization-requirements-7482.md b/.actual/rules/cross-cutting-custom-authorization-requirements-7482.md new file mode 100644 index 000000000000..69e9d4c455e7 --- /dev/null +++ b/.actual/rules/cross-cutting-custom-authorization-requirements-7482.md @@ -0,0 +1,38 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Custom Authorization Requirements + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces where authorization requirements must be declared via attributes on controller actions. + +### Rules + +- **R-AUTH-001** SHOULD: Custom authorization requirements SHOULD be defined as strongly-typed requirement classes that implement IAuthorizationRequirement and are used with the generic Authorize attribute. +- **R-AUTH-002** MUST: All controller action methods in AdminConsole and Admin namespaces MUST have either [Authorize] or [AllowAnonymous] attributes. +- **R-AUTH-003** MUST: Authorization requirement types MUST be defined in dedicated Authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns. +- **R-AUTH-004** MUST: Each custom requirement type MUST have a corresponding IAuthorizationHandler implementation registered in the dependency injection container. +- **R-AUTH-005** SHOULD: Requirement type names SHOULD be descriptive and clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement). +- **R-AUTH-006** MUST: Endpoints that intentionally allow anonymous access MUST explicitly apply [AllowAnonymous] to document the decision. +- **R-AUTH-007** MAY: Legacy endpoints requiring complex, multi-step authorization logic that cannot be expressed declaratively MAY implement imperative authorization checks (Exception EXC-001). +- **R-AUTH-008** MAY: Token-based public endpoints (e.g., invite links) MAY use AllowAnonymous with imperative token validation within the method body (Exception EXC-002). + +### Verify + +```bash +# Scan for controller actions without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controller files missing authorization using statements +find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI +- All new controller actions include appropriate authorization attributes or documented exceptions +- Security-focused integration tests verify authorization enforcement for each endpoint + + +Claude Code MUST NOT skip or defer verification. All controller actions MUST be scanned for missing authorization attributes. Violations MUST block CI builds and pull request merges until attributes are added or exceptions are documented and approved by the security team. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-authorization-requirements-789a.md b/.actual/rules/cross-cutting-custom-authorization-requirements-789a.md new file mode 100644 index 000000000000..6ef81bd1045b --- /dev/null +++ b/.actual/rules/cross-cutting-custom-authorization-requirements-789a.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Custom Authorization Requirements + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects, specifically HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources. + +### Rules + +- **R-AUTH-001** MUST: Custom authorization requirements MUST be expressed as strongly-typed requirement classes (e.g., ManageUsersRequirement, ProviderAdminRequirement) applied via generic [Authorize] attributes on controller action methods. +- **R-AUTH-002** MUST: All controller action methods returning IResult or IActionResult MUST have either [Authorize], [Authorize], or [AllowAnonymous] attributes declared. +- **R-AUTH-003** MUST: Custom authorization requirement classes MUST implement IAuthorizationRequirement and have corresponding registered handler implementations in the dependency injection container. +- **R-AUTH-004** MUST: Authorization handlers MUST be registered in the dependency injection container during application startup (typically in Program.cs or Startup.cs). +- **R-AUTH-005** SHOULD: For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions. +- **R-AUTH-006** SHOULD: Authorization requirement semantics SHOULD be documented in XML comments on requirement classes to aid developers in selecting appropriate attributes. +- **R-AUTH-007** MAY: [AllowAnonymous] usage MAY be applied to public endpoints for invite token validation or version checking, provided security rationale is documented and approved. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify all custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions +- All [AllowAnonymous] usage is documented with security rationale in code comments and approved by security team + + +Claude Code MUST NOT skip or defer verification of authorization attributes on controller actions. All new or modified controller actions MUST be verified to have appropriate authorization attributes before acceptance. Static analysis violations MUST block pull requests until resolved. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-authorization-requirements-fcd6.md b/.actual/rules/cross-cutting-custom-authorization-requirements-fcd6.md new file mode 100644 index 000000000000..c2911729b0e5 --- /dev/null +++ b/.actual/rules/cross-cutting-custom-authorization-requirements-fcd6.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Custom Authorization Requirements + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with [Authorize] attributes, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, administrative console controllers managing access control, and bulk operations affecting multiple protected resources. + +### Rules + +- **R-AUTH-001** SHOULD: Custom authorization requirements SHOULD implement IAuthorizationRequirement and be evaluated by corresponding AuthorizationHandler implementations. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- IAuthorizationService is injected in controller constructors as a private readonly field +- For bulk operations, authorization is verified for each resource in the collection before modification + + +Claude Code MUST NOT skip or defer verification of authorization enforcement patterns in protected controller actions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-result-types-8332.md b/.actual/rules/cross-cutting-custom-result-types-8332.md new file mode 100644 index 000000000000..e551d11a9513 --- /dev/null +++ b/.actual/rules/cross-cutting-custom-result-types-8332.md @@ -0,0 +1,31 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Custom Result Types + +These rules are ALWAYS ACTIVE for all ASP.NET Core minimal API endpoints, MVC controller action results, custom HTTP result types wrapping framework results, and integration test HTTP client interactions. + +### Rules + +- **R-IRESULT-001** MUST: Custom result types that wrap framework results MUST delegate ExecuteAsync to the inner result implementation. + +### Verify + +```bash +# Verify IResult interface usage in result types +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration tests use Server HTTP methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result types are sealed classes with internal constructors and readonly fields for inner result storage +- Factory methods or extension methods are exposed for creating custom results rather than public constructors + + +Clause Code MUST NOT skip or defer verification. All custom result type implementations MUST be inspected for proper IResult interface implementation and ExecuteAsync delegation. Integration test patterns MUST be validated against Server method usage requirements. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-custom-result-wrappers-23bd.md b/.actual/rules/cross-cutting-custom-result-wrappers-23bd.md new file mode 100644 index 000000000000..57875ed9108e --- /dev/null +++ b/.actual/rules/cross-cutting-custom-result-wrappers-23bd.md @@ -0,0 +1,30 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Custom Result Wrappers + +These rules are ALWAYS ACTIVE for ASP.NET Core minimal API endpoints, MVC controller action results, custom HTTP result types wrapping framework results, and integration test HTTP client interactions. + +### Rules + +- **R-IRESULT-001** SHOULD: Custom result wrappers SHOULD validate inner result instances using ArgumentNullException.ThrowIfNull + +### Verify + +```bash +# Verify IResult interface implementation in result types +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns (excluding direct Response.WriteAsync) +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration tests use Server HTTP methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result wrappers validate inner result instances using ArgumentNullException.ThrowIfNull + + +Claude Code MUST NOT skip or defer verification. All custom result wrapper implementations MUST be reviewed against R-IRESULT-001 and verified through the bash commands above before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-data-access-operations-1aca.md b/.actual/rules/cross-cutting-data-access-operations-1aca.md new file mode 100644 index 000000000000..18e158b48031 --- /dev/null +++ b/.actual/rules/cross-cutting-data-access-operations-1aca.md @@ -0,0 +1,31 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Data Access Operations + +These rules are ALWAYS ACTIVE for all SCIM API integration test files and data access operations within the test infrastructure. + +### Rules + +- **R-SCIM-DAL-001** MUST: Data access operations MUST call DatabaseContext.SaveChanges() to persist SCIM resource modifications. + +### Verify + +```bash +# Verify System.Text.Json is used for serialization +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify DatabaseContext.SaveChanges pattern is used +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify test authentication handlers use System.Security.Claims +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- JsonSerializerOptions are configured with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- DatabaseContext is properly scoped per test to avoid state leakage between test cases + + +Clause Code MUST NOT skip or defer verification of these rules during SCIM integration test development and review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-data-access-operations-44b0.md b/.actual/rules/cross-cutting-data-access-operations-44b0.md new file mode 100644 index 000000000000..061766caec2a --- /dev/null +++ b/.actual/rules/cross-cutting-data-access-operations-44b0.md @@ -0,0 +1,34 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Data Access Operations + +These rules are ALWAYS ACTIVE for all API controller classes and service boundary implementations that coordinate data access operations through command and query interfaces. + +### Rules + +- **R-CQSA-001** MUST: All data access operations invoked from API controllers MUST use asynchronous execution patterns with Task-based async/await semantics. +- **R-CQSA-002** MUST: All API controller action methods MUST return Task and use await when invoking command/query interface methods. +- **R-CQSA-003** MUST: Controllers MUST NOT perform direct data access (DbContext operations, SaveChanges, Query, Execute) within their class bodies. +- **R-CQSA-004** MUST: Data access operations MUST be delegated to injected command/query interfaces (e.g., ISceneExecutor, IDestroySceneCommand, IQueries) rather than direct persistence calls. +- **R-CQSA-005** SHOULD: Error handling at API boundaries SHOULD distinguish between aggregate failures (batch operations) and single execution failures, providing structured error responses. + +### Verify + +```bash +# Verify all controller action methods use async Task pattern +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controller classes +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files with async/await patterns +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access. +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments). +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar). +- Command/query interfaces are injected via constructor dependency injection and invoked consistently across all endpoints. + + +Clause Code MUST NOT skip or defer verification. All pull requests introducing or modifying API controllers MUST pass these verification checks before merge. Static analysis violations block CI pipeline until resolved or explicitly exempted with documented justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dbset-properties-organized-86b1.md b/.actual/rules/cross-cutting-dbset-properties-organized-86b1.md new file mode 100644 index 000000000000..4b93e7b0ac4f --- /dev/null +++ b/.actual/rules/cross-cutting-dbset-properties-organized-86b1.md @@ -0,0 +1,30 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Dbset Properties Organized + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, particularly the primary DatabaseContext class managing application-wide entity collections and all entity types representing persistent domain models. + +### Rules + +- **R-DBSET-001** SHOULD: DbSet properties SHOULD be organized by domain area or functional grouping within the context class to improve readability. + +### Verify + +```bash +# Count DbSet properties in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet declarations follow naming pattern +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming conventions +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting +- Related DbSet properties are grouped together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) + + +Claude Code MUST NOT skip or defer verification. All DbSet declarations must be validated during code review and build verification before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dbset-property-names-613d.md b/.actual/rules/cross-cutting-dbset-property-names-613d.md new file mode 100644 index 000000000000..1ddf8346a95d --- /dev/null +++ b/.actual/rules/cross-cutting-dbset-property-names-613d.md @@ -0,0 +1,29 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Dbset Property Names + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, specifically the DatabaseContext class and any entity types representing persistent domain models. + +### Rules + +- **R-DBSET-001** MUST: DbSet property names MUST use plural noun forms that clearly identify the entity collection (e.g., `DbSet Users`, `DbSet Ciphers`). + +### Verify + +```bash +# Count DbSet properties in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet declarations follow plural naming pattern +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public `DbSet` properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern `public DbSet EntityTypes { get; set; }` with consistent formatting + + +Claude Code MUST NOT skip or defer verification. All new entity types added to the codebase require corresponding DbSet properties with plural naming conventions. Pull requests adding entities without DbSet registration must be blocked during code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-dedicated-free-string-5122.md b/.actual/rules/cross-cutting-dedicated-free-string-5122.md new file mode 100644 index 000000000000..f7194bba1b87 --- /dev/null +++ b/.actual/rules/cross-cutting-dedicated-free-string-5122.md @@ -0,0 +1,36 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Dedicated Free String + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that expose cryptographic key generation and management functions to C callers, including all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-FFI-001** MUST: Provide a dedicated free_c_string function that is exported in the public API and documented for C callers to deallocate Rust-allocated string memory. +- **R-FFI-002** MUST: All public FFI functions returning strings use CString::into_raw() to transfer ownership and document the requirement to call free_c_string in their API documentation. +- **R-FFI-003** MUST: The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup of Rust-allocated memory. +- **R-FFI-004** MUST: Perform input validation to check for null pointers using .is_null() before dereferencing c_char pointers from C callers. +- **R-FFI-005** SHOULD: Include examples of correct string ownership transfer and deallocation in header files and API documentation. +- **R-FFI-006** SHOULD: Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns. + +### Verify + +```bash +# Count CString::into_raw and CString::from_raw usage +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists and is exported +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use CString::into_raw() and document the free_c_string requirement in their documentation +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No public FFI functions return raw c_char pointers without corresponding deallocation functions + + +Clause Code MUST NOT skip or defer verification. All FFI string handling violations in cryptographic key material code must be escalated to the security team. Memory sanitizer failures in CI pipeline require immediate remediation before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-distributed-cache-implementations-7a7e.md b/.actual/rules/cross-cutting-distributed-cache-implementations-7a7e.md new file mode 100644 index 000000000000..0eb740c0ce21 --- /dev/null +++ b/.actual/rules/cross-cutting-distributed-cache-implementations-7a7e.md @@ -0,0 +1,36 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Distributed Cache Implementations + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, Redis connection management and error handling for cache instances, and cache configuration sourced from Bit.Core.Settings. + +### Rules + +- **R-DIST-CACHE-001** MUST: Distributed cache implementations MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client library. +- **R-DIST-CACHE-002** MUST: All distributed cache registrations MUST use AddExtendedCache from Bit.Core.Utilities.ExtendedCacheServiceCollectionExtensions. +- **R-DIST-CACHE-003** MUST: Redis connection failures MUST be logged with LogError including cache name and exception details. +- **R-DIST-CACHE-004** MUST: Cache registration MUST occur through IServiceCollection extension methods that centralize connection management and error handling. +- **R-DIST-CACHE-005** SHOULD: Implement IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints. +- **R-DIST-CACHE-006** SHOULD: Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment. + +### Verify + +```bash +# Verify StackExchange.Redis package is referenced in Core project +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify AddExtendedCache is used for cache registration +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify no direct ConnectionMultiplexer.Connect calls outside approved patterns +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- No direct RedisCacheOptions configuration exists outside ExtendedCacheServiceCollectionExtensions +- Alternative cache providers are not used without ADR documentation justifying deviation + + +Claude Code MUST NOT skip or defer verification. Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review. Missing error handling for Redis connection failures blocks merge until logging is added. Exception requests must be submitted to the architectural review board with documented technical constraints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-distributed-caching-implementations-859c.md b/.actual/rules/cross-cutting-distributed-caching-implementations-859c.md new file mode 100644 index 000000000000..7e4f07d3b3f7 --- /dev/null +++ b/.actual/rules/cross-cutting-distributed-caching-implementations-859c.md @@ -0,0 +1,33 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Distributed Caching Implementations + +These rules are ALWAYS ACTIVE for all distributed caching implementations in Bit.Core and dependent services that require shared caching across multi-instance deployments. + +### Rules + +- **R-DIST-CACHE-001** MUST: Distributed caching implementations MUST use Microsoft.Extensions.Caching.Distributed abstractions (IDistributedCache) rather than direct Redis client dependencies. + +### Verify + +```bash +# Verify IDistributedCache usage in distributed cache implementations +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Check for IDistributedCache interface usage +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration pattern +grep -r 'AddExtendedCache' --include='*.cs' + +# Detect direct Redis client usage outside infrastructure layer +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + + +Clause Code MUST NOT skip or defer verification of R-DIST-CACHE-001 compliance. All distributed caching code must be reviewed against the IDistributedCache abstraction requirement before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-domain-business-logic-5463.md b/.actual/rules/cross-cutting-domain-business-logic-5463.md new file mode 100644 index 000000000000..710f9481bb9b --- /dev/null +++ b/.actual/rules/cross-cutting-domain-business-logic-5463.md @@ -0,0 +1,34 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Domain Business Logic + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including all SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes, services implementing IScimContext and ICurrentContext interfaces, controllers decorated with authorization policy attributes, and middleware pipeline components between UseAuthentication and UseAuthorization. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD NOT: Domain business logic SHOULD NOT contain inline authorization checks; enforcement SHOULD occur at policy enforcement points in the middleware pipeline. + +### Verify + +```bash +# Verify AddAuthorization configuration with named 'Scim' policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify production policies require 'api.scim' scope claim +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +# Verify no inline authorization checks in domain business logic +grep -r 'if.*User.*IsAuthenticated\|if.*User.*HasClaim\|if.*context.*Authorize' --include='*.cs' | grep -v 'Startup.cs' | grep -v 'Factory.cs' | grep -v 'Test' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- No inline authorization checks are found in domain service methods or business logic classes +- Authorization policy attributes are consistently applied to all SCIM API controllers + + +Claude Code MUST NOT skip or defer verification. All SCIM endpoints must enforce authorization via policy-based configuration at the middleware level, never through inline domain logic checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-each-fake-rsa-889f.md b/.actual/rules/cross-cutting-each-fake-rsa-889f.md new file mode 100644 index 000000000000..e474e9a9f7ca --- /dev/null +++ b/.actual/rules/cross-cutting-each-fake-rsa-889f.md @@ -0,0 +1,37 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Each Fake Rsa + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK, particularly test modules in util/RustSdk/rust/src/ that validate RSA key material, cipher operations, key generation, and cryptographic workflows. + +### Rules + +- **R-FAKE-RSA-001** MUST: Each fake RSA key constant MUST contain a complete PEM-encoded private key block including BEGIN PRIVATE KEY and END PRIVATE KEY markers. +- **R-FAKE-RSA-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` annotation or within `mod tests` blocks to prevent production compilation. +- **R-FAKE-RSA-003** MUST: Fake RSA key constants MUST use descriptive naming with sequential numbering: `_FAKE_RSA_KEY_0` through `_FAKE_RSA_KEY_N`. +- **R-FAKE-RSA-004** MUST: No references to `_FAKE_RSA_KEY_` constants MAY appear in production code paths outside test modules. +- **R-FAKE-RSA-005** SHOULD: At least 5 distinct fake RSA key constants SHOULD be available in util/RustSdk/rust/src/rsa_keys.rs to support tests requiring multiple distinct keys. +- **R-FAKE-RSA-006** SHOULD: Fake key constants SHOULD be generated once using `openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem` and embedded as string literals. +- **R-FAKE-RSA-007** SHOULD: Module-level comments SHOULD document key generation parameters (algorithm, key size, format) for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Verify PEM-encoded private key blocks exist in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Run rsa_keys tests to validate key material +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to `_FAKE_RSA_KEY_` constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries +- Module-level comments document key generation parameters and maintenance guidance + + +Claude Code MUST NOT skip or defer verification. All rules R-FAKE-RSA-001 through R-FAKE-RSA-007 MUST be verified before accepting changes to cryptographic test fixtures. CI build MUST fail if fake key constants are referenced outside test-scoped modules. Code review MUST block merge if test fixtures lack proper conditional compilation guards. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-each-fake-rsa-9e21.md b/.actual/rules/cross-cutting-each-fake-rsa-9e21.md new file mode 100644 index 000000000000..b46b69c513f8 --- /dev/null +++ b/.actual/rules/cross-cutting-each-fake-rsa-9e21.md @@ -0,0 +1,36 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Each Fake Rsa + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-FAKE-RSA-001** SHOULD: Each `_FAKE_RSA_KEY_*` constant SHOULD be accompanied by inline documentation explaining its intended test scenario (e.g., key rotation, multi-signature validation). +- **R-FAKE-RSA-002** MUST: All `_FAKE_RSA_KEY_*` constants MUST be defined in a dedicated test fixtures module (e.g., `rsa_keys.rs`) with `const` visibility and PEM PKCS#8 format. +- **R-FAKE-RSA-003** MUST: No references to `_FAKE_RSA_KEY_*` constants MUST exist outside `#[cfg(test)]` blocks or test-only modules. +- **R-FAKE-RSA-004** MUST: CI pipeline MUST include automated checks that fail builds if production code references test key constants. +- **R-FAKE-RSA-005** SHOULD: Each fake key constant SHOULD include inline documentation explaining its test scenario with clear rationale. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key validation tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- All 5 fake RSA keys (0-4) are present and valid +- RSA key validation tests pass successfully + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code containing hardcoded RSA private keys in test fixtures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-endpoints-modifying-collection-9595.md b/.actual/rules/cross-cutting-endpoints-modifying-collection-9595.md new file mode 100644 index 000000000000..1cdba58dd079 --- /dev/null +++ b/.actual/rules/cross-cutting-endpoints-modifying-collection-9595.md @@ -0,0 +1,31 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Endpoints Modifying Collection + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically endpoints that modify collection access for users. + +### Rules + +- **R-AUTHZ-001** MUST: Endpoints modifying collection access for users MUST call AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess requirement before persisting changes. + +### Verify + +```bash +# Verify IAuthorizationService is injected in organization user controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called with BulkCollectionOperations.ModifyUserAccess +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' +``` + +**Accept when:** +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService as a private readonly field +- All endpoints modifying collection access call AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess requirement before persistence operations +- Authorization failures consistently throw NotFoundException to prevent enumeration attacks +- Collection modification endpoints fetch collection entities via ICollectionRepository before authorization checks +- Self-modification scenarios check organizationAbility.AllowAdminAccessToAllCollectionItems before allowing collection/group additions + + +Claude Code MUST NOT skip or defer verification of these authorization checks. All endpoints modifying collection access MUST be verified to call AuthorizeAsync with the required BulkCollectionOperations.ModifyUserAccess requirement before any changes are persisted. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-endpoints-that-allow-4471.md b/.actual/rules/cross-cutting-endpoints-that-allow-4471.md new file mode 100644 index 000000000000..ae528f467d58 --- /dev/null +++ b/.actual/rules/cross-cutting-endpoints-that-allow-4471.md @@ -0,0 +1,30 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Endpoints That Allow + +These rules are ALWAYS ACTIVE for all controllers in the Bit.Api.AdminConsole.Controllers namespace and all HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests. + +### Rules + +- **R-AUTHZ-001** SHOULD: Endpoints that allow anonymous access SHOULD use the AllowAnonymous attribute explicitly to document the intentional bypass of authorization. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async Task methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements +- Endpoints that intentionally allow anonymous access are explicitly marked with [AllowAnonymous] + + +Claude Code MUST NOT skip or defer verification. Static analysis during CI pipeline using custom Roslyn analyzers or linting rules is mandatory. Code review must verify authorization attributes on all new endpoints. Security-focused integration tests must verify authorization enforcement for each endpoint. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-entity-framework-dbcontext-abc6.md b/.actual/rules/cross-cutting-entity-framework-dbcontext-abc6.md new file mode 100644 index 000000000000..920afafca6ff --- /dev/null +++ b/.actual/rules/cross-cutting-entity-framework-dbcontext-abc6.md @@ -0,0 +1,30 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Entity Framework Dbcontext + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, particularly the primary DatabaseContext class managing application-wide entity collections and all persistent domain entity types (User, Organization, Cipher, Collection, etc.). + +### Rules + +- **R-EF-001** MUST: Entity Framework DbContext implementations MUST expose each persistent entity type as a public DbSet property with explicit getter and setter. + +### Verify + +```bash +# Count DbSet declarations in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet property declarations follow the pattern +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming conventions +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern `public DbSet EntityTypes { get; set; }` with consistent formatting +- Related DbSet properties are grouped together with comments indicating domain boundaries + + +Claude Code MUST NOT skip or defer verification. All new entity types added to the codebase require corresponding DbSet property declarations in DatabaseContext. Build failures from missing entity registrations halt CI pipeline until resolved. Code review must verify DbSet registration for all new persistent entity types before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-entity-types-requiring-8ef3.md b/.actual/rules/cross-cutting-entity-types-requiring-8ef3.md new file mode 100644 index 000000000000..f5d069120a5d --- /dev/null +++ b/.actual/rules/cross-cutting-entity-types-requiring-8ef3.md @@ -0,0 +1,37 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Entity Types Requiring + +These rules are ALWAYS ACTIVE for all Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace, particularly the primary DatabaseContext class managing application-wide entity collections and all entity types representing persistent domain models. + +### Rules + +- **R-DBSET-001** MUST: All entity types requiring database persistence MUST be registered as DbSet properties in the primary DatabaseContext class. +- **R-DBSET-002** MUST: DbSet property declarations follow the pattern `public DbSet EntityTypes { get; set; }` with consistent plural naming conventions. +- **R-DBSET-003** SHOULD: Group related DbSet properties together with comments indicating domain boundaries (e.g., `// Access Control Entities`, `// Vault Entities`). +- **R-DBSET-004** SHOULD: Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic. +- **R-DBSET-005** MUST NOT: Expose view models or DTOs used only for API responses without database persistence as DbSet properties. +- **R-DBSET-006** MUST NOT: Register temporary or in-memory data structures not requiring ORM mapping as DbSet properties. +- **R-DBSET-007** MAY: Keyless entities (read-only query result types) may defer DbSet registration with explicit documentation of exemption rationale in OnModelCreating configuration. + +### Verify + +```bash +# Count DbSet declarations in DatabaseContext +grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l + +# Verify project builds successfully +dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental + +# Verify DbSet declarations follow naming pattern (plural nouns) +grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +``` + +**Accept when:** +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming conventions. +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined. +- DbSet property declarations follow the pattern `public DbSet EntityTypes { get; set; }` with consistent formatting. +- Related DbSet properties are grouped with domain boundary comments. +- Complex entity mappings use IEntityTypeConfiguration classes rather than inline configuration. + + +Claude Code MUST NOT skip or defer verification. All new entity types added to the codebase require corresponding DbSet registration in DatabaseContext. Pull requests adding entity types without DbSet properties MUST be rejected during code review. Build failures from missing entity registrations MUST halt the CI pipeline. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-error-log-entries-5cd6.md b/.actual/rules/cross-cutting-error-log-entries-5cd6.md new file mode 100644 index 000000000000..3c62fcb85a60 --- /dev/null +++ b/.actual/rules/cross-cutting-error-log-entries-5cd6.md @@ -0,0 +1,29 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Error Log Entries + +These rules are ALWAYS ACTIVE for all cache service registration extensions and distributed cache initialization code that uses StackExchangeRedis via Microsoft.Extensions.Caching.StackExchangeRedis. + +### Rules + +- **R-REDIS-001** MUST: Error log entries for Redis connection failures MUST include the cache name as a structured logging parameter (e.g., {CacheName}). + +### Verify + +```bash +# Check for LogError calls related to Redis connection failures +grep -r 'LogError.*Failed to connect to Redis' src/ + +# Count ConnectionMultiplexer.Connect calls wrapped with try-catch +grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' + +# Run cache initialization tests with detailed logging +dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + + +Claude Code MUST NOT skip or defer verification. All Redis connection initialization code MUST include error logging with structured cache name parameters before merging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-exception-handling-tests-94de.md b/.actual/rules/cross-cutting-exception-handling-tests-94de.md new file mode 100644 index 000000000000..e9aa5936d720 --- /dev/null +++ b/.actual/rules/cross-cutting-exception-handling-tests-94de.md @@ -0,0 +1,31 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Exception Handling Tests + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.SecretsManager.Queries namespace that verify query classes coordinating access policy updates and secret synchronization operations. + +### Rules + +- **R-EX-001** SHOULD: Exception handling tests SHOULD verify that queries throw expected exceptions (NotFoundException) when external dependencies return invalid state. + +### Verify + +```bash +# Verify sutProvider pattern usage for interface-based isolation +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Verify operation classification assertions in test results +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit tests without database dependencies +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- Exception handling tests explicitly verify NotFoundException is thrown when repository dependencies return invalid state +- Mock repository dependencies are injected via sutProvider pattern rather than instantiated directly + + +Claude Code MUST NOT skip or defer verification. Code review MUST confirm new query test classes follow sutProvider pattern and mock repository dependencies. CI pipeline execution MUST verify unit test suite passes with no database connection configuration. Tests exceeding 100ms per test execution time MUST be flagged for review of external dependencies. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-exception-logging-within-5e08.md b/.actual/rules/cross-cutting-exception-logging-within-5e08.md new file mode 100644 index 000000000000..dda2cfa8bc79 --- /dev/null +++ b/.actual/rules/cross-cutting-exception-logging-within-5e08.md @@ -0,0 +1,29 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Exception Logging Within + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes, controller actions that invoke external services after authorization checks, admin and provider management endpoints handling sensitive resource operations, and exception handlers and catch blocks within authorized action methods. + +### Rules + +- **R-EX-001** MUST: Exception logging within authorized actions MUST use LogError with the exception object as the first parameter to preserve stack traces and exception metadata. + +### Verify + +```bash +# Check for controllers with [Authorize] that lack ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters in controller files +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in logging statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + + +Clause Code MUST NOT skip or defer verification. All three verify commands must pass before accepting changes to authorized controller exception logging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-extended-cache-utilities-aaaf.md b/.actual/rules/cross-cutting-extended-cache-utilities-aaaf.md new file mode 100644 index 000000000000..021796ba5dd7 --- /dev/null +++ b/.actual/rules/cross-cutting-extended-cache-utilities-aaaf.md @@ -0,0 +1,41 @@ +# Use Redis via StackExchange.Redis for Distributed Caching with Extended Cache Utilities + +These rules are ALWAYS ACTIVE for all distributed caching implementations in Bit.Core and dependent services that use Redis through StackExchange.Redis and Microsoft.Extensions.Caching.Distributed abstractions. + +### Rules + +- **R-CACHE-001** MUST: Use IDistributedCache interface for all distributed cache operations rather than direct Redis client references. +- **R-CACHE-002** MUST: Register distributed cache implementations through AddExtendedCache or similar extension methods in Bit.Core.Utilities service collection extensions. +- **R-CACHE-003** MUST: Log Redis connection failures with structured logging including cache name context using Microsoft.Extensions.Logging. +- **R-CACHE-004** MAY: Extended cache utilities MAY provide additional configuration options beyond standard IDistributedCache for Redis-specific features. +- **R-CACHE-005** SHOULD: Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies. +- **R-CACHE-006** SHOULD: Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments. +- **R-CACHE-007** SHOULD: Implement circuit breaker patterns and cache-aside fallback logic to handle Redis connection failures gracefully. + +### Verify + +```bash +# Verify IDistributedCache usage without direct Redis client references +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Check IDistributedCache interface usage +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration pattern +grep -r 'AddExtendedCache' --include='*.cs' + +# Detect direct Redis client usage outside infrastructure layer +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchange.Redis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer +- Cache key naming conventions are documented and consistently applied across services +- Connection string configuration includes appropriate retry and timeout policies + + +Claude Code MUST NOT skip or defer verification of these rules. Code review checklist verification of IDistributedCache usage and proper service collection registration is mandatory. Static analysis rules detecting direct Redis client usage outside infrastructure layer must be applied. Integration tests validating cache behavior with both Redis and in-memory implementations are required. Architecture decision record compliance audits during sprint retrospectives are mandatory. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-external-client-calls-7e79.md b/.actual/rules/cross-cutting-external-client-calls-7e79.md new file mode 100644 index 000000000000..aa38bf7922c3 --- /dev/null +++ b/.actual/rules/cross-cutting-external-client-calls-7e79.md @@ -0,0 +1,34 @@ +# Establish HTTP Client Boundaries for External Service Integration: External Client Calls + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, identity providers, and SSO configuration endpoints. + +### Rules + +- **R-EX-001** SHOULD: External client calls SHOULD use async/await patterns (Server.GetAsync, Server.PostAsync, Server.PutAsync, Server.PatchAsync) to prevent thread pool exhaustion. +- **R-EX-002** MUST: All HTTP clients MUST be created through IHttpClientFactory via dependency injection rather than direct instantiation with `new HttpClient()`. +- **R-EX-003** MUST: All HTTP clients that accept user-supplied URLs MUST include AddSsrfProtection() in their registration pipeline. +- **R-EX-004** SHOULD: HTTP clients SHOULD be registered as named clients in Startup.cs ConfigureServices method using services.AddHttpClient(name) for configuration isolation and handler pipeline customization. +- **R-EX-005** SHOULD: Test infrastructure SHOULD configure custom authentication handlers using services.AddAuthentication(scheme).AddScheme() before HTTP client registration to enable mocking without network dependencies. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are present +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct `new HttpClient()` instantiations outside documented legacy exceptions (EXC-001, EXC-002) +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- All external client registrations are centralized in Startup.cs ConfigureServices method with clear visibility into dependencies + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations MUST pass code review checklist verification. Direct HttpClient instantiation patterns MUST be detected and blocked. Missing SSRF protection on user-facing endpoints MUST trigger security review and block deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-external-http-client-d376.md b/.actual/rules/cross-cutting-external-http-client-d376.md new file mode 100644 index 000000000000..a721ce794f28 --- /dev/null +++ b/.actual/rules/cross-cutting-external-http-client-d376.md @@ -0,0 +1,33 @@ +# Establish HTTP Client Boundaries for External Service Integration: External Http Client + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, and identity providers. + +### Rules + +- **R-EX-001** MUST: External HTTP client instances MUST be created through IHttpClientFactory using services.AddHttpClient() registration rather than direct HttpClient instantiation. +- **R-EX-002** MUST: All HTTP clients that accept user-supplied URLs MUST include AddSsrfProtection() in their registration pipeline. +- **R-EX-003** SHOULD: Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients. +- **R-EX-004** SHOULD: Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are detected +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- IHttpClientFactory is injected into all services making outbound HTTP requests + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations MUST pass code review checklist verification and static analysis checks before merge. Violations are blocking until refactored to comply with R-EX-001 and R-EX-002. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-external-service-clients-a488.md b/.actual/rules/cross-cutting-external-service-clients-a488.md new file mode 100644 index 000000000000..87efe956210c --- /dev/null +++ b/.actual/rules/cross-cutting-external-service-clients-a488.md @@ -0,0 +1,30 @@ +# Adopt HTTP Client Abstraction for External Service Integration: External Service Clients + +These rules are ALWAYS ACTIVE for all HTTP client implementations integrating with external services and APIs across multiple language runtimes (Rust and C#), including third-party APIs, remote data sources, and distributed system components outside the service boundary. + +### Rules + +- **R-EX-001** SHOULD: External service clients SHOULD implement rate limiting when integrating with third-party APIs to prevent quota exhaustion. + +### Verify + +```bash +# Count AddHttpClient registrations in .NET services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Count direct HttpClient instantiations outside tests (should be 0 in production) +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Count safe FFI string marshaling patterns in Rust +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients +- Rate limiting is configured for all third-party API integrations using framework-provided or distributed rate limiting infrastructure + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns outside test contexts is mandatory. Code review checklist verification of HTTP client registration is required for all new external service integrations. Integration test suite validation of HTTP client behavior under timeout, retry, and failure scenarios must pass before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-failed-authorization-checks-d17b.md b/.actual/rules/cross-cutting-failed-authorization-checks-d17b.md new file mode 100644 index 000000000000..59caa4a28052 --- /dev/null +++ b/.actual/rules/cross-cutting-failed-authorization-checks-d17b.md @@ -0,0 +1,37 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Failed Authorization Checks + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, particularly operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** MUST: Failed authorization checks MUST throw NotFoundException rather than UnauthorizedException to prevent information disclosure about entity existence. +- **R-AUTHZ-002** MUST: All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic. +- **R-AUTHZ-003** MUST: Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes. +- **R-AUTHZ-004** MUST: Authorization checks use typed requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) evaluated by IAuthorizationService. +- **R-AUTHZ-005** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-AUTHZ-006** SHOULD: Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections. +- **R-AUTHZ-007** SHOULD: Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges. + +### Verify + +```bash +# Count authorization checks using BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Count NotFoundException throws following AuthorizeAsync calls +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService injections in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- Integration tests verify NotFoundException responses for unauthorized access attempts across all endpoints + + +Clause Code MUST NOT skip or defer verification of authorization patterns. All organization user management endpoints must be audited for consistent IAuthorizationService usage and NotFoundException exception handling before merging. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-cryptographic-key-ace5.md b/.actual/rules/cross-cutting-fake-cryptographic-key-ace5.md new file mode 100644 index 000000000000..b1ed8f6edd85 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-cryptographic-key-ace5.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Fake Cryptographic Key + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs), test fixtures, and the public API surface exposed through FFI to managed C# code. + +### Rules + +- **R-FFI-001** SHOULD: Fake cryptographic key constants SHOULD be marked with naming conventions that make their test-only nature explicit. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Count fake RSA key constants with test-only naming +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated C# bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Claude Code MUST NOT skip or defer verification. Automated CI checks MUST verify that build.rs successfully generates C# bindings and that generated files compile. Code review MUST check for proper use of csbindgen configuration and test fixture naming conventions. Static analysis tools MUST scan for usage of test constants in non-test production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-key-229c.md b/.actual/rules/cross-cutting-fake-rsa-key-229c.md new file mode 100644 index 000000000000..fb009e3e9aad --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-key-229c.md @@ -0,0 +1,36 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK. + +### Rules + +- **R-FAKE-RSA-001** MUST: Fake RSA key constants MUST be prefixed with `_FAKE_RSA_KEY_` or similar naming convention to clearly distinguish test fixtures from production key material. +- **R-FAKE-RSA-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` annotation or within `mod tests` blocks to ensure test-only compilation. +- **R-FAKE-RSA-003** MUST: No references to `_FAKE_RSA_KEY_` constants MUST appear in production code paths outside test modules. +- **R-FAKE-RSA-004** MUST: All fake key constants MUST contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-FAKE-RSA-005** SHOULD: At least 5 distinct fake RSA key constants SHOULD be available with sequential numbering (`_FAKE_RSA_KEY_0` through `_FAKE_RSA_KEY_4`) to support tests requiring multiple distinct keys. +- **R-FAKE-RSA-006** SHOULD: Fake key constants SHOULD be defined in a dedicated `rsa_keys.rs` module to maintain clear boundaries between test infrastructure and production cryptographic code. +- **R-FAKE-RSA-007** SHOULD: Module-level comments SHOULD document the key generation parameters (algorithm, key size, format) for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Count embedded private key blocks in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Verify rsa_keys tests execute successfully +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in `util/RustSdk/rust/src/rsa_keys.rs` with sequential numbering +- No references to `_FAKE_RSA_KEY_` constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if fake key constants are referenced outside test-scoped modules. Code review MUST block merge if test fixtures lack proper conditional compilation guards. Security scan MUST alert if known test keys appear in production artifacts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-key-2471.md b/.actual/rules/cross-cutting-fake-rsa-key-2471.md new file mode 100644 index 000000000000..1e974ad301e8 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-key-2471.md @@ -0,0 +1,35 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Fake Rsa Key + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-FAKE-RSA-001** MUST: All `_FAKE_RSA_KEY_*` constants MUST contain PEM-encoded PKCS#8 format private keys with `BEGIN PRIVATE KEY` and `END PRIVATE KEY` delimiters. +- **R-FAKE-RSA-002** MUST: All `_FAKE_RSA_KEY_*` constants MUST be defined in a dedicated test fixtures module (e.g., `rsa_keys.rs`) with `const` visibility to create a single audit point. +- **R-FAKE-RSA-003** MUST: No references to `_FAKE_RSA_KEY_*` constants SHALL exist outside `#[cfg(test)]` blocks or test-only modules. +- **R-FAKE-RSA-004** SHOULD: Each `_FAKE_RSA_KEY_*` constant SHOULD include inline documentation explaining its intended test scenario (e.g., key rotation, multi-key testing). +- **R-FAKE-RSA-005** SHOULD: CI pipeline SHOULD include automated checks that fail builds if production code references test key constants. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key test suite passes +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct PEM PKCS#8 format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- Verification commands execute successfully with no production references detected + + +Claude Code MUST NOT skip or defer verification. All rules R-FAKE-RSA-001 through R-FAKE-RSA-005 are mandatory for code review and CI/CD pipeline enforcement. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-key-bfc4.md b/.actual/rules/cross-cutting-fake-rsa-key-bfc4.md new file mode 100644 index 000000000000..5503ab8087d6 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-key-bfc4.md @@ -0,0 +1,35 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Fake Rsa Key + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-FAKE-RSA-001** MUST: Fake RSA key constants MUST be declared with `const` visibility and MUST NOT be exported from the module's public API. +- **R-FAKE-RSA-002** MUST: All `_FAKE_RSA_KEY_*` constants MUST be consolidated into a dedicated test fixtures module or `rsa_keys.rs` file to create a single audit point. +- **R-FAKE-RSA-003** MUST: No references to `_FAKE_RSA_KEY_*` constants MUST exist outside `#[cfg(test)]` blocks or test-only modules. +- **R-FAKE-RSA-004** MUST: Each fake RSA key constant MUST be PEM-encoded PKCS#8 format. +- **R-FAKE-RSA-005** SHOULD: Each fake key constant SHOULD include inline documentation explaining its intended test scenario. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key test suite passes +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys present with correct PEM PKCS#8 format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- All verification commands execute successfully + + +Claude Code MUST NOT skip or defer verification of these rules. All R-FAKE-RSA-* rules are mandatory and must be checked before accepting changes to cryptographic test fixtures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-key-cbea.md b/.actual/rules/cross-cutting-fake-rsa-key-cbea.md new file mode 100644 index 000000000000..064334b12633 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-key-cbea.md @@ -0,0 +1,35 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK. + +### Rules + +- **R-FAKE-RSA-001** MUST NOT: Fake RSA key constants MUST NOT be used in production code paths or exposed through public APIs. +- **R-FAKE-RSA-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks. +- **R-FAKE-RSA-003** MUST: At least 5 distinct fake RSA key constants MUST be available with sequential numbering (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4). +- **R-FAKE-RSA-004** MUST: All fake key constants MUST contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-FAKE-RSA-005** SHOULD: Fake key constants SHOULD use descriptive names following the pattern `const _FAKE_RSA_KEY_N: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----";` +- **R-FAKE-RSA-006** SHOULD: Module-level comments SHOULD document key generation parameters (algorithm, key size, format) for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Verify fake keys are defined in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Run rsa_keys tests +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to `_FAKE_RSA_KEY_` constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if fake key constants are referenced outside test-scoped modules. Code review MUST block merge if test fixtures lack proper conditional compilation guards. Security scan MUST alert if known test keys appear in production artifacts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-key-fffb.md b/.actual/rules/cross-cutting-fake-rsa-key-fffb.md new file mode 100644 index 000000000000..94fd773a52c4 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-key-fffb.md @@ -0,0 +1,36 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK. + +### Rules + +- **R-FAKE-RSA-001** SHOULD: Fake RSA key constants SHOULD be organized in a dedicated module (e.g., rsa_keys.rs) separate from production cryptographic code. +- **R-FAKE-RSA-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks. +- **R-FAKE-RSA-003** MUST: At least 5 distinct fake RSA key constants MUST be available with sequential numbering (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4). +- **R-FAKE-RSA-004** MUST: No references to _FAKE_RSA_KEY_ constants MAY appear in production code paths outside test modules. +- **R-FAKE-RSA-005** MUST: All fake key constants MUST contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-FAKE-RSA-006** SHOULD: Fake keys SHOULD be generated once using `openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem` and embedded as string literals. +- **R-FAKE-RSA-007** SHOULD: Key generation parameters (algorithm, key size, format) SHOULD be documented in module-level comments for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Count fake RSA keys in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Run rsa_keys tests +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + + +Claude Code MUST NOT skip or defer verification. CI build fails if fake key constants are referenced outside test-scoped modules. Code review blocks merge if test fixtures lack proper conditional compilation guards. Security scan alerts trigger immediate review if known test keys appear in production artifacts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-keys-15e4.md b/.actual/rules/cross-cutting-fake-rsa-keys-15e4.md new file mode 100644 index 000000000000..aff71c6aa000 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-keys-15e4.md @@ -0,0 +1,41 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop code consuming Rust cryptographic functions via FFI. + +### Rules + +- **R-FAKE-RSA-001** SHOULD: Fake RSA keys SHOULD be co-located with the cryptographic implementation code they test, within the same module or adjacent test module. +- **R-FAKE-RSA-002** MUST: All fake RSA keys MUST be prefixed with `_FAKE_RSA_KEY_` followed by zero-indexed sequential numbering (e.g., `_FAKE_RSA_KEY_0` through `_FAKE_RSA_KEY_4`). +- **R-FAKE-RSA-003** MUST: Fake RSA keys MUST NOT appear in production source files or production code paths; they are test fixtures only. +- **R-FAKE-RSA-004** MUST: Each fake RSA key MUST include a comment header explicitly stating it is a test fixture and must never be used in production. +- **R-FAKE-RSA-005** SHOULD: Fake RSA keys SHOULD be declared as const string literals containing full PEM-encoded 2048-bit RSA private keys to ensure deterministic test execution across all environments. +- **R-FAKE-RSA-006** MUST: At least 5 distinct fake RSA keys MUST be available in the test fixtures module to support multi-party protocols, key rotation simulation, and edge case testing. +- **R-FAKE-RSA-007** SHOULD: C# test code consuming the Rust SDK via csbindgen SHOULD reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. + +### Verify + +```bash +# Verify no fake keys appear in production code (outside test modules) +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify at least 5 distinct fake RSA keys exist +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +# Verify naming convention compliance +grep '_FAKE_RSA_KEY_[0-9]' util/RustSdk/rust/src/rsa_keys.rs | wc -l | awk '$1 >= 5 {print "Naming convention verified"}' +``` + +**Accept when:** +- All test code using RSA operations references `_FAKE_RSA_KEY_N` constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming (`_FAKE_RSA_KEY_0` through `_FAKE_RSA_KEY_4`) +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Each fake key constant includes a comment header stating it is a test fixture +- Static analysis confirms no `_FAKE_RSA_KEY_` patterns appear in non-test files + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis checks MUST fail if fake key patterns are detected outside test modules. Code review MUST block merges if cryptographic tests do not use standardized fake keys or if new fake keys do not follow the naming convention. Security team notification MUST be triggered for any violation detected in production branches. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-keys-3f21.md b/.actual/rules/cross-cutting-fake-rsa-keys-3f21.md new file mode 100644 index 000000000000..0f9a506bc3ba --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-keys-3f21.md @@ -0,0 +1,42 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop test suites. + +### Rules + +- **R-FAKE-RSA-001** MUST NOT: Fake RSA keys MUST NOT be used in production code paths or for any real cryptographic security purposes. +- **R-FAKE-RSA-002** MUST: All fake RSA keys MUST be placed in a dedicated test fixtures module with clear documentation that keys are for testing only. +- **R-FAKE-RSA-003** MUST: Fake RSA keys MUST use the naming convention `_FAKE_RSA_KEY_N` with zero-indexed sequential numbering. +- **R-FAKE-RSA-004** MUST: Each fake key block MUST include a comment header explaining it is a test fixture and must never be used in production. +- **R-FAKE-RSA-005** MUST: At least 5 distinct fake RSA keys MUST be available in the test fixtures module for multi-party protocol testing and key rotation scenarios. +- **R-FAKE-RSA-006** SHOULD: C# test code consuming the Rust SDK via csbindgen SHOULD reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. +- **R-FAKE-RSA-007** MUST: Static analysis rules MUST detect `_FAKE_RSA_KEY_` pattern usage outside test modules and fail CI builds if violations are found. +- **R-FAKE-RSA-008** MUST: Code review MUST verify that cryptographic tests use standardized fake keys and that new fake keys follow the naming convention. + +### Verify + +```bash +# Verify no fake keys appear in production code +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify at least 5 fake keys exist +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +# Verify naming convention compliance +grep '_FAKE_RSA_KEY_[0-9]' util/RustSdk/rust/src/rsa_keys.rs | wc -l | awk '$1 >= 5 {print "Naming convention verified"}' +``` + +**Accept when:** +- All test code using RSA operations references `_FAKE_RSA_KEY_N` constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming (`_FAKE_RSA_KEY_0` through `_FAKE_RSA_KEY_4`) +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Each fake key block includes a comment header documenting it is a test fixture +- Static analysis verification confirms no `_FAKE_RSA_KEY_` patterns in production binaries or non-test source files + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for test code exercising cryptographic operations. Violations detected by static analysis MUST cause CI build failure. Code review MUST block merges that violate these rules. Security team notification MUST be triggered for any violation detected in production branches. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-fake-rsa-keys-af1e.md b/.actual/rules/cross-cutting-fake-rsa-keys-af1e.md new file mode 100644 index 000000000000..43354bd62116 --- /dev/null +++ b/.actual/rules/cross-cutting-fake-rsa-keys-af1e.md @@ -0,0 +1,37 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop test suites. + +### Rules + +- **R-FAKE-RSA-001** MUST: Fake RSA keys MUST be declared as const string literals containing complete PEM-encoded PRIVATE KEY blocks in PKCS#8 format. +- **R-FAKE-RSA-002** MUST: Fake RSA keys MUST use the naming convention `_FAKE_RSA_KEY_N` with zero-indexed sequential numbering. +- **R-FAKE-RSA-003** MUST: Fake RSA keys MUST NOT appear in production source files or production code paths; they are restricted to test modules only. +- **R-FAKE-RSA-004** MUST: All test code using RSA operations MUST reference `_FAKE_RSA_KEY_N` constants from the dedicated test fixtures module. +- **R-FAKE-RSA-005** SHOULD: Place fake RSA keys in a dedicated module (e.g., `src/test_fixtures/rsa_keys.rs`) with clear documentation that keys are for testing only. +- **R-FAKE-RSA-006** SHOULD: Add a comment header above each fake key block explaining it is a test fixture and must never be used in production. +- **R-FAKE-RSA-007** SHOULD: In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. +- **R-FAKE-RSA-008** MAY: Document the purpose of each key if they represent specific test scenarios (e.g., `_FAKE_RSA_KEY_EXPIRED` for expiration testing). + +### Verify + +```bash +# Verify no fake keys appear in production code (outside test modules) +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify minimum 5 distinct fake RSA keys are present +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' +``` + +**Accept when:** +- All test code using RSA operations references `_FAKE_RSA_KEY_N` constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material +- Static analysis detects no `_FAKE_RSA_KEY_` pattern usage outside test modules + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for test code exercising cryptographic operations. Violations in production code paths trigger CI build failure and security team notification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-boundary-functions-918a.md b/.actual/rules/cross-cutting-ffi-boundary-functions-918a.md new file mode 100644 index 000000000000..72cf092510e5 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-boundary-functions-918a.md @@ -0,0 +1,32 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Ffi Boundary Functions + +These rules are ALWAYS ACTIVE for all FFI boundary functions that expose cryptographic key generation through C interoperability, including memory management functions for C-allocated strings and cryptographic keys, and input validation for cipher and RSA key operations. + +### Rules + +- **R-FFI-001** SHOULD: FFI boundary functions SHOULD use std::ffi types exclusively for C interoperability rather than custom pointer wrappers. + +### Verify + +```bash +# Verify all public FFI functions for key generation use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in public API for memory deallocation +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used for FFI boundary operations +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- All new FFI functions that allocate memory provide a corresponding free_* function with documented caller responsibility +- Input validation is implemented at FFI boundaries before passing to internal cryptographic functions +- std::panic::catch_unwind wraps CString conversions to prevent panics from crossing FFI boundaries + + +Clause Code MUST NOT skip or defer verification. All FFI boundary functions must be reviewed for paired allocation/deallocation patterns. Memory leaks detected in CI must block merge until resolved. Panics at FFI boundaries must be converted to error returns before production deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-boundary-validation-d076.md b/.actual/rules/cross-cutting-ffi-boundary-validation-d076.md new file mode 100644 index 000000000000..0fb332700322 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-boundary-validation-d076.md @@ -0,0 +1,31 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Boundary Validation + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +### Rules + +- **R-FFI-001** MUST: FFI boundary validation failures MUST return error codes or null pointers to callers rather than panicking. + +### Verify + +```bash +# Check that all public FFI functions accepting c_char pointers include CStr validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify at least 5 fake RSA key fixtures exist for test coverage +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Confirm RSA key validation tests pass +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs +- Memory ownership semantics are documented in FFI function comments +- Negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) are present + + +Claude Code MUST NOT skip or defer verification. All FFI functions crossing the Rust-C boundary must be validated using CStr/CString patterns before any pointer dereference. Security team sign-off is required for new FFI functions. CI pipeline must enforce these checks and block merges that violate the rule. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-boundary-validation-f057.md b/.actual/rules/cross-cutting-ffi-boundary-validation-f057.md new file mode 100644 index 000000000000..729b56010b65 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-boundary-validation-f057.md @@ -0,0 +1,35 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Boundary Validation + +These rules are ALWAYS ACTIVE for all public extern "C" functions in util/RustSdk/rust/src/ that accept c_char pointer parameters, FFI helper functions processing C string inputs, and cryptographic key generation functions receiving string parameters across the FFI boundary. + +### Rules + +- **R-FFI-001** MUST: Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers. +- **R-FFI-002** MUST: Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-003** MUST: FFI boundary validation MUST occur before any cryptographic operations (cipher, rsa_keys, key generation) to prevent invalid data from reaching security-critical code paths. +- **R-FFI-004** MUST: For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks. +- **R-FFI-005** SHOULD: Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior. +- **R-FFI-006** SHOULD: Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files. + +### Verify + +```bash +# Verify all extern "C" functions accepting c_char pointers use CStr::from_ptr +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify count of CString::into_raw matches string-returning FFI functions +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi +``` + +**Accept when:** +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling +- Cryptographic operations (cipher, rsa_keys, key generation) receive only validated string inputs from the FFI boundary + + +Claude Code MUST NOT skip or defer verification. All R-FFI rules marked MUST are non-negotiable for FFI boundary code. Violations detected by grep patterns or test failures MUST trigger CI build failure and code review rejection. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-entry-points-dcb8.md b/.actual/rules/cross-cutting-ffi-entry-points-dcb8.md new file mode 100644 index 000000000000..9e781a4519de --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-entry-points-dcb8.md @@ -0,0 +1,43 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Ffi Entry Points + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in `util/RustSdk/rust/src/lib.rs` that handle cryptographic key material, including public key generation APIs and cipher/RSA key data structures exposed across FFI boundaries. + +### Rules + +- **R-FFI-001** MUST: All FFI entry points handling key material MUST implement input validation for C string parameters before conversion to Rust types. +- **R-FFI-002** MUST: Use `#[repr(C)]` attribute on all data structures crossing FFI boundaries to ensure stable memory layout. +- **R-FFI-003** MUST: Wrap all `CStr::from_ptr` calls in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-FFI-004** MUST: Provide memory management functions (e.g., `free_c_string`) for all FFI-allocated strings and document ownership semantics in function comments. +- **R-FFI-005** SHOULD: Define mock traits (e.g., `CipherOps`, `RsaKeyOps`) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations. +- **R-FFI-006** SHOULD: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage (c_char, CStr, CString) +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Run tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 + +# Verify #[repr(C)] on FFI-exposed structs +grep -B1 'pub struct' util/RustSdk/rust/src/lib.rs | grep -c '#\[repr(C)\]' + +# Check for CStr::from_ptr usage with validation +grep -n 'CStr::from_ptr' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions handling key material use `std::ffi` types (`c_char`, `CStr`, `CString`) with explicit validation. +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations. +- Memory management functions (`free_c_string`) are provided and documented for all FFI-allocated strings. +- All data structures crossing FFI boundaries are annotated with `#[repr(C)]`. +- All `CStr::from_ptr` calls include null pointer checks and UTF-8 validation. +- Integration tests using real cryptographic operations pass alongside unit tests with mocks. + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if FFI functions lack required validation or memory management functions. Pull requests adding new FFI entry points MUST require security team approval. Runtime panics in FFI code MUST trigger incident review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-exposed-cryptographic-b670.md b/.actual/rules/cross-cutting-ffi-exposed-cryptographic-b670.md new file mode 100644 index 000000000000..bfa09257ca45 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-exposed-cryptographic-b670.md @@ -0,0 +1,40 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Ffi Exposed Cryptographic + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, specifically within the Rust SDK module (util/RustSdk/rust/src/) and C# interop test code consuming Rust cryptographic functions via csbindgen-generated bindings. + +### Rules + +- **R-CRYPTO-001** MUST: FFI-exposed cryptographic functions that accept key material MUST have corresponding test cases using the standardized fake RSA keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4). +- **R-CRYPTO-002** MUST: Fake RSA keys MUST NOT appear in production source files outside of dedicated test modules (src/test_fixtures/ or equivalent test-only paths). +- **R-CRYPTO-003** MUST: All fake RSA keys MUST follow the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering. +- **R-CRYPTO-004** MUST: Each fake RSA key constant MUST include a comment header explicitly stating it is a test fixture and must never be used in production. +- **R-CRYPTO-005** SHOULD: Fake RSA keys SHOULD be placed in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only. +- **R-CRYPTO-006** SHOULD: C# test code consuming the Rust SDK via csbindgen SHOULD reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. + +### Verify + +```bash +# Verify no fake keys appear in production code (outside test modules) +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify at least 5 distinct fake RSA keys exist +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +# Verify fake key naming convention +grep -E '_FAKE_RSA_KEY_[0-9]+' util/RustSdk/rust/src/rsa_keys.rs | wc -l | awk '$1 >= 5 {print "Naming convention verified"}' +``` + +**Accept when:** +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Each fake RSA key constant includes a comment header stating it is a test fixture +- Static analysis confirms no _FAKE_RSA_KEY_ pattern usage in non-test files + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for test code exercising cryptographic operations in public API protocols. Violations MUST be caught by CI pipeline static analysis checks and code review before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-accepting-0ca0.md b/.actual/rules/cross-cutting-ffi-functions-accepting-0ca0.md new file mode 100644 index 000000000000..cf64f0aa0e4d --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-accepting-0ca0.md @@ -0,0 +1,31 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Functions Accepting + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +### Rules + +- **R-FFI-001** MUST: All FFI functions accepting c_char pointers MUST validate input using CStr::from_ptr before dereferencing or converting to Rust types. + +### Verify + +```bash +# Check for CStr validation patterns in all public FFI functions +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify fake RSA key fixtures exist for testing +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Run RSA key validation tests +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs +- Memory ownership semantics are documented in FFI function comments +- Negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) are present + + +Claude Code MUST NOT skip or defer verification. All FFI functions accepting c_char pointers MUST be validated using CStr::from_ptr patterns before merging. Security team sign-off is required for new FFI functions. CI build MUST fail if validation patterns are missing. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-accepting-2b77.md b/.actual/rules/cross-cutting-ffi-functions-accepting-2b77.md new file mode 100644 index 000000000000..6903e3eda3fc --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-accepting-2b77.md @@ -0,0 +1,35 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Accepting + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, and string marshaling code in lib.rs and cipher.rs modules. + +### Rules + +- **R-FFI-001** MUST: All FFI functions accepting C string pointers (c_char) MUST convert them to CStr using CStr::from_ptr before dereferencing or using the string data. +- **R-FFI-002** MUST: Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing. +- **R-FFI-003** MUST: Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop. +- **R-FFI-004** SHOULD: Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing. +- **R-FFI-005** SHOULD: Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called. +- **R-FFI-006** SHOULD: Add FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators. + +### Verify + +```bash +# Verify all CStr::from_ptr conversions are in unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" +``` + +**Accept when:** +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + + +Claude Code MUST NOT skip or defer verification of FFI string input validation. All violations discovered in code review or CI must trigger immediate remediation or documented exception approval by the security team. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-accepting-aff1.md b/.actual/rules/cross-cutting-ffi-functions-accepting-aff1.md new file mode 100644 index 000000000000..87234b6a1dc3 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-accepting-aff1.md @@ -0,0 +1,40 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Accepting + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept C string pointers (c_char) at cryptographic interop boundaries, particularly in util/RustSdk/rust/src/lib.rs and related FFI modules handling sensitive cryptographic material. + +### Rules + +- **R-FFI-001** MUST: All FFI functions accepting C string pointers (c_char) MUST validate input using std::ffi::CStr before dereferencing or converting to Rust types. +- **R-FFI-002** MUST: Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers. +- **R-FFI-003** MUST: Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements. +- **R-FFI-004** MUST: For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw(). +- **R-FFI-005** MUST: Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, and empty strings. +- **R-FFI-006** SHOULD: Profile FFI call overhead and document performance characteristics for callers to mitigate validation latency concerns. +- **R-FFI-007** SHOULD: Provide clear documentation and examples for C callers on proper memory management and error handling at FFI boundaries. + +### Verify + +```bash +# Count FFI functions with c_char or CStr/CString usage +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify all public FFI functions use CStr validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI tests for validation coverage +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +# Verify no raw c_char dereferencing without CStr +grep -r 'unsafe.*\*.*c_char' util/RustSdk/rust/src/lib.rs | grep -v 'CStr::from_ptr' || echo "No unsafe c_char dereferencing found without CStr validation" +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- Error handling is properly propagated to C callers with documented error return codes +- No raw c_char pointer dereferencing occurs without CStr validation in FFI boundaries + + +Clause Code MUST NOT skip or defer verification of FFI input validation. All public FFI functions handling cryptographic material or accepting string pointers require explicit CStr/CString validation before processing. Violations must be flagged in code review and CI pipeline checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-accepting-bf2a.md b/.actual/rules/cross-cutting-ffi-functions-accepting-bf2a.md new file mode 100644 index 000000000000..93f6643f56bf --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-accepting-bf2a.md @@ -0,0 +1,37 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Accepting + +These rules are ALWAYS ACTIVE for all FFI functions in the Rust SDK that accept c_char pointer parameters, particularly those handling cryptographic operations or exposed as public API boundaries. + +### Rules + +- **R-FFI-001** MUST: All FFI functions accepting c_char pointer parameters MUST validate input using CStr::from_ptr or equivalent before dereferencing. +- **R-FFI-002** MUST: All extern C functions returning strings MUST use CString::into_raw for safe memory transfer to callers. +- **R-FFI-003** MUST: All FFI functions accepting c_char pointers MUST check for null pointers before calling CStr::from_ptr. +- **R-FFI-004** MUST: Validation of c_char inputs MUST occur before any cryptographic operations (cipher, rsa_keys, SymmetricCryptoKey). +- **R-FFI-005** SHOULD: Use Result return types with error codes mapped to C-compatible integers for validation failures. +- **R-FFI-006** SHOULD: Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- Null pointer checks are present before CStr::from_ptr calls +- No raw pointer arithmetic or manual null-terminator checking bypasses CStr/CString wrappers + + +Claude Code MUST NOT skip or defer verification. All FFI functions accepting c_char parameters MUST be validated using CStr/CString conversion before any use. Violations in cryptographic code paths trigger security incident review. Exceptions require explicit approval from two security team members with documented justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-not-5d4a.md b/.actual/rules/cross-cutting-ffi-functions-not-5d4a.md new file mode 100644 index 000000000000..bd126278bca3 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-not-5d4a.md @@ -0,0 +1,37 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Not + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that accept c_char pointers, handle cryptographic material, or are marked with #[no_mangle] or extern "C". + +### Rules + +- **R-FFI-001** MUST NOT: FFI functions MUST NOT assume input c_char pointers are valid UTF-8 without explicit validation using CStr::from_ptr() or equivalent safe conversion. +- **R-FFI-002** MUST: All extern "C" functions accepting c_char pointers MUST validate inputs using std::ffi::CStr before dereferencing. +- **R-FFI-003** MUST: All extern "C" functions returning strings MUST use CString::new() and CString::into_raw() for safe memory transfer to callers. +- **R-FFI-004** MUST: FFI functions handling cryptographic operations (cipher, rsa_keys, SymmetricCryptoKey) MUST validate string inputs before passing to cryptographic functions. +- **R-FFI-005** SHOULD: FFI functions SHOULD use Result return types with error codes mapped to C-compatible integers for validation failures. +- **R-FFI-006** MUST: The free_c_string function MUST implement memory reclamation as: unsafe { CString::from_raw(ptr) } to prevent memory leaks. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern "C" functions accepting c_char pointers use CStr::from_ptr for validation +- All extern "C" functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- No null pointer dereferences occur without prior null checks +- Memory ownership is clearly documented for all returned CString pointers + + +Claude Code MUST NOT skip or defer verification. All FFI functions in scope MUST pass the verification commands before acceptance. Violations in cryptographic code paths trigger mandatory security team review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-return-7a63.md b/.actual/rules/cross-cutting-ffi-functions-return-7a63.md new file mode 100644 index 000000000000..32acfead5b26 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-return-7a63.md @@ -0,0 +1,30 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Return + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept c_char pointers or handle cryptographic material across C interop boundaries. + +### Rules + +- **R-FFI-001** SHOULD: FFI functions SHOULD return error codes or null pointers to C callers when input validation fails rather than panicking. + +### Verify + +```bash +# Count FFI functions using CStr/CString patterns +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify all public FFI functions use CStr::from_ptr or CString patterns +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI test coverage for validation scenarios +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- Error handling is properly propagated to C callers via return codes or null pointers + + +Clause Code MUST NOT skip or defer verification of FFI input validation. All public FFI functions handling c_char pointers or cryptographic material require explicit CStr/CString validation before use. Violations must be flagged during code review and CI pipeline checks. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-return-d4fe.md b/.actual/rules/cross-cutting-ffi-functions-return-d4fe.md new file mode 100644 index 000000000000..1dffefa1a131 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-return-d4fe.md @@ -0,0 +1,35 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Return + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, and string marshaling code in lib.rs and cipher.rs modules. + +### Rules + +- **R-FFI-001** MUST: Wrap all `CStr::from_ptr` calls in unsafe blocks with explicit null pointer checks using `is_null()` before dereferencing. +- **R-FFI-002** MUST: Provide a public `free_c_string` function that accepts `*mut c_char` and calls `CString::from_raw` followed by automatic drop. +- **R-FFI-003** MUST: Use `CStr::to_str()` or `to_string_lossy()` to convert validated C strings to Rust `&str` or `String` types for internal processing. +- **R-FFI-004** MUST: Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until `free_c_string` is called. +- **R-FFI-005** SHOULD: Add FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators. +- **R-FFI-006** MAY: FFI functions MAY return error codes or null pointers to indicate validation failures rather than panicking. + +### Verify + +```bash +# Verify all CStr::from_ptr conversions are in unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" +``` + +**Accept when:** +- All `CStr::from_ptr` conversions are contained within unsafe blocks with null pointer validation +- A public `free_c_string` function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use `CStr`/`CString` for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + + +Clause Code MUST NOT skip or defer verification. All FFI string functions must pass the verify commands before merge. Security team must approve all exceptions with explicit risk assessment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-returning-07be.md b/.actual/rules/cross-cutting-ffi-functions-returning-07be.md new file mode 100644 index 000000000000..faa6d02a410a --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-returning-07be.md @@ -0,0 +1,34 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Functions Returning + +These rules are ALWAYS ACTIVE for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers, including public extern "C" functions in util/RustSdk/rust/src/lib.rs and FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs. + +### Rules + +- **R-FFI-001** MUST: FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function. +- **R-FFI-002** MUST: All public extern "C" functions accepting c_char pointer parameters MUST perform null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers. +- **R-FFI-003** MUST: FFI functions MUST use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-004** SHOULD: FFI function comments and generated C header files SHOULD document string encoding requirements (UTF-8, null-terminated). +- **R-FFI-005** SHOULD: Test suite SHOULD include cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling. + +### Verify + +```bash +# Verify all extern "C" functions use CStr::from_ptr +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Count CString::into_raw usage (should match string-returning FFI functions) +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi +``` + +**Accept when:** +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling +- Grep verification for extern "C" functions missing CStr conversion returns empty result + + +Claude Code MUST NOT skip or defer verification of FFI string input validation. All R-FFI rules are mandatory for code crossing the C FFI boundary. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-returning-b569.md b/.actual/rules/cross-cutting-ffi-functions-returning-b569.md new file mode 100644 index 000000000000..0a31a31351a9 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-returning-b569.md @@ -0,0 +1,34 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Returning + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept c_char pointers or return strings across the C interop boundary, particularly those handling cryptographic material. + +### Rules + +- **R-FFI-001** MUST: FFI functions accepting c_char pointers MUST use `CStr::from_ptr()` wrapped in unsafe blocks with explicit null pointer checks before dereferencing. +- **R-FFI-002** MUST: FFI functions returning strings to C callers MUST use `std::ffi::CString` and provide a corresponding `free_c_string` function to prevent memory leaks. +- **R-FFI-003** MUST: All FFI functions handling cryptographic material (ciphers, RSA keys, symmetric keys) MUST validate input using CStr/CString before processing. +- **R-FFI-004** SHOULD: Convert `CStr` to Rust `String` or `&str` using `to_str()` or `to_string_lossy()` depending on UTF-8 requirements. +- **R-FFI-005** SHOULD: Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, and empty strings. + +### Verify + +```bash +# Count FFI functions with c_char/CStr/CString usage +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify all public FFI functions use proper validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI tests for validation coverage +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use `CStr::from_ptr()` for validation before use +- All FFI functions returning strings use `CString` and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- No raw c_char pointer dereferencing occurs without CStr validation in FFI boundary code + + +Clause Code MUST NOT skip or defer verification of FFI input validation. All violations detected by CI pipeline or code review MUST be remediated before merge. Security review is required for any FFI function handling cryptographic material without input validation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-returning-daae.md b/.actual/rules/cross-cutting-ffi-functions-returning-daae.md new file mode 100644 index 000000000000..217b7364bb45 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-returning-daae.md @@ -0,0 +1,37 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Returning + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, and string marshaling code in lib.rs and cipher.rs modules. + +### Rules + +- **R-FFI-001** MUST: FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function for memory cleanup. +- **R-FFI-002** MUST: Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing. +- **R-FFI-003** MUST: Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop. +- **R-FFI-004** MUST: Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing. +- **R-FFI-005** MUST: Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called. +- **R-FFI-006** SHOULD: Add FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators. + +### Verify + +```bash +# Verify all CStr::from_ptr conversions are in unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" +``` + +**Accept when:** +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data +- Memory ownership contract is documented in function comments for all FFI string functions +- Integration tests exercise FFI boundary with invalid inputs (null pointers, invalid UTF-8) + + +Claude Code MUST NOT skip or defer verification. All FFI string functions MUST be reviewed for CStr/CString compliance before approval. Violations block pull requests in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-returning-f766.md b/.actual/rules/cross-cutting-ffi-functions-returning-f766.md new file mode 100644 index 000000000000..f4ae70dc9598 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-returning-f766.md @@ -0,0 +1,37 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Returning + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that accept c_char pointers or return string data to external callers, particularly those handling cryptographic material. + +### Rules + +- **R-FFI-001** MUST: FFI functions returning string data to external callers MUST use CString::into_raw or equivalent to ensure null-terminated C-compatible strings. +- **R-FFI-002** MUST: All extern "C" functions accepting c_char pointers MUST validate inputs using CStr::from_ptr wrapped in unsafe blocks, checking for null before dereferencing. +- **R-FFI-003** MUST: FFI functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) MUST perform input validation before sensitive processing. +- **R-FFI-004** SHOULD: FFI functions converting c_char pointers to Rust strings SHOULD use .to_str() for strict UTF-8 validation or .to_string_lossy() when lossy conversion is acceptable. +- **R-FFI-005** SHOULD: FFI functions returning CString pointers SHOULD be paired with a corresponding free_c_string function implemented as: unsafe { CString::from_raw(ptr) }. +- **R-FFI-006** SHOULD: FFI functions with validation failures SHOULD use Result return types with error codes mapped to C-compatible integers. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern "C" functions accepting c_char pointers use CStr::from_ptr for validation +- All extern "C" functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- Memory ownership is clearly documented for all returned CString pointers +- free_c_string or equivalent cleanup function exists for all CString returns + + +Claude Code MUST NOT skip or defer verification. All FFI functions crossing the C boundary MUST be validated against these rules before approval. Violations in cryptographic code paths MUST trigger security team review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-that-ed1f.md b/.actual/rules/cross-cutting-ffi-functions-that-ed1f.md new file mode 100644 index 000000000000..764d93120227 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-that-ed1f.md @@ -0,0 +1,38 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Ffi Functions That + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions exposed through C FFI boundaries in the Rust SDK, including all FFI boundary functions that allocate or manipulate cryptographic material, memory management functions for C-allocated strings and cryptographic keys, and input validation for cipher and RSA key operations. + +### Rules + +- **R-FFI-001** MUST: FFI functions that allocate memory MUST provide corresponding deallocation functions (e.g., free_c_string) in the public API. +- **R-FFI-002** MUST: All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it. +- **R-FFI-003** MUST: Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead. +- **R-FFI-004** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-FFI-005** SHOULD: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production. +- **R-FFI-006** SHOULD: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns. + +### Verify + +```bash +# Verify all public FFI functions for key generation use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in the public API for memory deallocation +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used for FFI boundary operations +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- Code review confirms all FFI boundary functions have paired allocation/deallocation +- Static analysis detects no CString conversions without corresponding error handling +- Memory leak detection in CI using valgrind or similar tools passes on FFI integration tests +- No panics at FFI boundaries; all errors are converted to error returns + + +Claude Code MUST NOT skip or defer verification. All FFI functions without paired deallocation functions MUST be rejected in code review. Memory leaks detected in CI MUST block merge until resolved. Panics at FFI boundaries MUST be converted to error returns before production deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-use-1f6f.md b/.actual/rules/cross-cutting-ffi-functions-use-1f6f.md new file mode 100644 index 000000000000..9a8b67e72392 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-use-1f6f.md @@ -0,0 +1,35 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Ffi Functions Use + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that expose cryptographic key generation and management functions to C consumers, including all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-FFI-001** SHOULD: FFI functions SHOULD use null pointer checks and return error codes rather than panicking on invalid input. +- **R-FFI-002** MUST: All public FFI functions returning strings MUST use `CString::into_raw()` to transfer ownership and document the requirement to call `free_c_string`. +- **R-FFI-003** MUST: A `free_c_string` function MUST exist and be exported in the public API to reclaim ownership using `CString::from_raw()` before deallocation. +- **R-FFI-004** MUST: Input validation MUST check for null pointers using `.is_null()` before dereferencing `c_char` pointers from C. +- **R-FFI-005** SHOULD: FFI functions SHOULD include documentation with examples of correct string ownership transfer and deallocation. + +### Verify + +```bash +# Count CString usage patterns in FFI functions +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use `CString::into_raw()` and document `free_c_string` requirement +- A `free_c_string` function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing `c_char` parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No FFI functions panic on invalid input; all return error codes instead + + +Clause Code MUST NOT skip or defer verification. Code review MUST verify CString usage patterns in FFI functions. Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) MUST pass. Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) MUST pass in CI pipeline. Security audit of FFI boundary code MUST be completed during release cycles. CI build MUST fail if FFI functions return raw pointers without corresponding deallocation functions. Code review MUST block merge if FFI string handling lacks proper documentation. Memory sanitizer failures in CI MUST be resolved before merge. Security team escalation is required for violations in cryptographic key handling code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-use-4489.md b/.actual/rules/cross-cutting-ffi-functions-use-4489.md new file mode 100644 index 000000000000..1765c0671c1c --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-use-4489.md @@ -0,0 +1,35 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Functions Use + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +### Rules + +- **R-FFI-001** MUST: FFI functions MUST use CString::new for outbound string conversions to ensure null-termination and prevent interior null bytes. +- **R-FFI-002** MUST: All c_char pointer parameters MUST be wrapped with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation before dereferencing. +- **R-FFI-003** MUST: Memory ownership semantics MUST be documented in FFI function comments, specifying whether caller or callee owns memory and when free_c_string must be called. +- **R-FFI-004** SHOULD: Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers. +- **R-FFI-005** SHOULD: Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds. + +### Verify + +```bash +# Check for CStr validation in all FFI functions +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify fake RSA key fixtures exist +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Run RSA key validation tests +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs +- Memory ownership semantics are documented in FFI function comments +- CString::new is used for all outbound string conversions with proper null-termination handling + + +Claude Code MUST NOT skip or defer verification. All FFI functions must pass CStr validation checks before merge. Security team sign-off is required for new FFI functions. CI build fails if validation patterns are missing. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-use-846b.md b/.actual/rules/cross-cutting-ffi-functions-use-846b.md new file mode 100644 index 000000000000..22bb0ef1da92 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-use-846b.md @@ -0,0 +1,35 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Use + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers, functions handling cryptographic material, and any function marked with #[no_mangle] or extern "C" that accepts string parameters. + +### Rules + +- **R-FFI-001** MAY: FFI functions MAY use std::panic::catch_unwind to prevent panics from crossing FFI boundaries. +- **R-FFI-002** MUST: All extern "C" functions accepting c_char pointers MUST use CStr::from_ptr for validation. +- **R-FFI-003** MUST: All extern "C" functions returning strings MUST use CString::into_raw for safe memory transfer. +- **R-FFI-004** MUST: Input validation MUST occur before cryptographic operations on FFI-sourced data. +- **R-FFI-005** MUST: Null pointer checks MUST precede CStr::from_ptr dereferencing in unsafe blocks. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage patterns +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern "C" functions accepting c_char pointers use CStr::from_ptr for validation +- All extern "C" functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- Null pointer checks are present before all CStr::from_ptr calls + + +Claude Code MUST NOT skip or defer verification. All FFI functions must pass automated grep/pattern matching and clippy lints before acceptance. Security-focused code review is mandatory for all FFI boundary changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-functions-validate-87be.md b/.actual/rules/cross-cutting-ffi-functions-validate-87be.md new file mode 100644 index 000000000000..827940b10d4f --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-functions-validate-87be.md @@ -0,0 +1,36 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Functions Validate + +These rules are ALWAYS ACTIVE for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers, specifically in util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs. + +### Rules + +- **R-FFI-001** MUST: FFI functions MUST validate that c_char pointers are non-null before dereferencing or converting to CStr. +- **R-FFI-002** MUST: All public extern "C" functions accepting c_char pointer parameters perform CStr::from_ptr conversion with null checks before accessing data. +- **R-FFI-003** MUST: FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function. +- **R-FFI-004** MUST: Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-005** SHOULD: Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior. +- **R-FFI-006** SHOULD: Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files. + +### Verify + +```bash +# Verify all extern "C" functions use CStr conversion +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify string-returning FFI functions use CString::into_raw +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi +``` + +**Accept when:** +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data. +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function. +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling. +- Grep verification for extern "C" functions missing CStr conversion returns empty result. +- Count of CString::into_raw matches count of string-returning FFI functions. + + +Claude Code MUST NOT skip or defer verification. All FFI functions accepting c_char pointers MUST be validated using the verify commands above before accepting changes. Violations result in CI build failure and code review rejection. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-modules-document-9333.md b/.actual/rules/cross-cutting-ffi-modules-document-9333.md new file mode 100644 index 000000000000..1415af8331f7 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-modules-document-9333.md @@ -0,0 +1,39 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Modules Document + +These rules are ALWAYS ACTIVE for all public `extern "C"` functions in util/RustSdk/rust/src/ that accept C-style string pointers (c_char) from external callers across FFI boundaries. + +### Rules + +- **R-FFI-001** MUST: All public `extern "C"` functions accepting `c_char` pointer parameters MUST perform null checks before calling `CStr::from_ptr` to prevent undefined behavior from null pointers. +- **R-FFI-002** MUST: All `c_char` pointer inputs MUST be validated using `CStr::to_str()` for UTF-8 encoding before passing to cryptographic operations (cipher, rsa_keys, key generation functions). +- **R-FFI-003** MUST: FFI functions returning strings MUST use `CString::new().unwrap().into_raw()` and provide a corresponding `free_c_string` cleanup function to prevent memory leaks. +- **R-FFI-004** SHOULD: FFI modules SHOULD document the expected string encoding (UTF-8) and null-termination requirements in function signatures and comments. +- **R-FFI-005** SHOULD: FFI functions SHOULD return explicit error codes to C callers rather than panicking when string validation fails. +- **R-FFI-006** MAY: Performance-critical FFI paths MAY request exception (EXC-002) with explicit unsafe block justifications and caller contract requirements, subject to security team approval. + +### Verify + +```bash +# Verify all extern "C" functions use CStr conversion +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify CString::into_raw usage matches string-returning functions +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi + +# Check for missing safety documentation on FFI functions +cargo clippy --package rust-sdk -- -W clippy::missing_safety_doc -W clippy::not_unsafe_ptr_arg_deref +``` + +**Accept when:** +- All public `extern "C"` functions accepting `c_char` pointers perform `CStr::from_ptr` conversion with null checks before accessing data +- FFI functions returning strings use `CString::into_raw` and provide corresponding `free_c_string` cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling +- FFI function comments document UTF-8 encoding and null-termination requirements +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) validate all string inputs before processing + + +Claude Code MUST NOT skip or defer verification. All R-FFI-001, R-FFI-002, and R-FFI-003 rules are mandatory for FFI boundary code. Violations result in CI build failure and code review rejection. Security team lead approval required for any exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-modules-use-10d2.md b/.actual/rules/cross-cutting-ffi-modules-use-10d2.md new file mode 100644 index 000000000000..bf5ec6fdc429 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-modules-use-10d2.md @@ -0,0 +1,36 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Ffi Modules Use + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs, cryptographic key generation and management functions exposed to C, and all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-FFI-001** MUST: All public FFI functions returning strings use `CString::into_raw()` to transfer ownership and document the requirement to call `free_c_string`. +- **R-FFI-002** MUST: A `free_c_string` function must exist, be exported in the public API, and use `CString::from_raw()` to reclaim ownership before deallocation. +- **R-FFI-003** MUST: Input validation must check for null pointers using `.is_null()` before dereferencing `c_char` pointers from C. +- **R-FFI-004** SHOULD: Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns. +- **R-FFI-005** SHOULD: Document the memory ownership contract in header files and API documentation, including examples of correct usage. +- **R-FFI-006** MAY: FFI modules MAY use `std::collections::HashSet` for tracking allocated resources to detect double-free attempts in debug builds. + +### Verify + +```bash +# Count CString::into_raw and CString::from_raw usage +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use `CString::into_raw()` and document `free_c_string` requirement +- A `free_c_string` function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing `c_char` parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No static string literals are deallocated (exception EXC-001) + + +Clause Code MUST NOT skip or defer verification. All FFI string handling patterns must pass code review checklist verification, static analysis with clippy lints (clippy::not_unsafe_ptr_arg_deref), integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline, and security audit of FFI boundary code during release cycles. CI build must fail if FFI functions return raw pointers without corresponding deallocation functions. Code review must block merge if FFI string handling lacks proper documentation. Memory sanitizer failures in CI require immediate fix before merge. Security team escalation required for violations in cryptographic key handling code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-modules-use-71f1.md b/.actual/rules/cross-cutting-ffi-modules-use-71f1.md new file mode 100644 index 000000000000..7fdc798f0e80 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-modules-use-71f1.md @@ -0,0 +1,37 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Modules Use + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers, key generation functions, and any FFI function handling cryptographic material. + +### Rules + +- **R-FFI-001** MUST: All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use. +- **R-FFI-002** MUST: All FFI functions returning strings use CString and provide corresponding free functions. +- **R-FFI-003** MUST: Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers. +- **R-FFI-004** MUST: Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements. +- **R-FFI-005** MUST: For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw(). +- **R-FFI-006** SHOULD: Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings. +- **R-FFI-007** MAY: FFI modules MAY use additional validation layers (length checks, character set validation) beyond CStr/CString for defense in depth. + +### Verify + +```bash +# Count FFI functions using CStr/CString +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify public FFI functions have proper validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI tests for validation coverage +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- Clippy lints pass for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Integration tests validate error handling for malformed FFI inputs + + +Clause Code MUST NOT skip or defer verification. All public FFI functions handling cryptographic material require input validation. CI pipeline MUST fail on detection of raw c_char pointer dereferencing without CStr validation. Security review is required for any FFI function handling cryptographic material without input validation. Post-merge review flags violations for immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-modules-use-f2ec.md b/.actual/rules/cross-cutting-ffi-modules-use-f2ec.md new file mode 100644 index 000000000000..4912b88257fb --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-modules-use-f2ec.md @@ -0,0 +1,29 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Modules Use + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +### Rules + +- **R-FFI-001** SHOULD: FFI modules SHOULD use std::collections::HashSet or similar structures to track allocated resources requiring cleanup via free_c_string. + +### Verify + +```bash +# Check for CStr validation patterns in FFI functions +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify fake RSA key fixtures exist +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Run RSA key validation tests +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + + +Claude Code MUST NOT skip or defer verification. All FFI functions must be validated using CStr patterns, fake key fixtures must be present and tested, and the cargo test suite must pass before accepting this rule as satisfied. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-string-validation-6a74.md b/.actual/rules/cross-cutting-ffi-string-validation-6a74.md new file mode 100644 index 000000000000..9732e13bd085 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-string-validation-6a74.md @@ -0,0 +1,35 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi String Validation + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept or return string parameters, cryptographic operations exposed through FFI, and string marshaling code in lib.rs and cipher.rs modules. + +### Rules + +- **R-FFI-001** MUST: Wrap all `CStr::from_ptr` calls in unsafe blocks with explicit null pointer checks using `is_null()` before dereferencing. +- **R-FFI-002** MUST: FFI string validation MUST occur at the earliest point in the function before any cryptographic operations are performed. +- **R-FFI-003** MUST: Provide a public `free_c_string` function that accepts `*mut c_char` and calls `CString::from_raw` followed by automatic drop. +- **R-FFI-004** SHOULD: Use `CStr::to_str()` or `to_string_lossy()` to convert validated C strings to Rust `&str` or `String` types for internal processing. +- **R-FFI-005** SHOULD: Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until `free_c_string` is called. +- **R-FFI-006** SHOULD: Add FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators. + +### Verify + +```bash +# Verify all CStr::from_ptr conversions are in unsafe blocks +grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" + +# Count FFI functions accepting c_char +grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l + +# Verify free_c_string function exists +grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" +``` + +**Accept when:** +- All `CStr::from_ptr` conversions are contained within unsafe blocks with null pointer validation +- A public `free_c_string` function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use `CStr`/`CString` for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + + +Clause Code MUST NOT skip or defer verification. All FFI functions must pass the verify commands before merge. Security team must approve all exceptions with explicit risk assessment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-ffi-string-validation-d47f.md b/.actual/rules/cross-cutting-ffi-string-validation-d47f.md new file mode 100644 index 000000000000..381cfbf83c21 --- /dev/null +++ b/.actual/rules/cross-cutting-ffi-string-validation-d47f.md @@ -0,0 +1,38 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi String Validation + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers, functions handling cryptographic material, and any function marked with #[no_mangle] or extern "C" that accepts string parameters. + +### Rules + +- **R-FFI-001** SHOULD: FFI string validation SHOULD occur before any cryptographic operations or sensitive data processing. +- **R-FFI-002** MUST: All extern "C" functions accepting c_char pointers MUST use CStr::from_ptr for validation wrapped in unsafe blocks with null checks. +- **R-FFI-003** MUST: All extern "C" functions returning strings MUST use CString::into_raw for safe memory transfer to callers. +- **R-FFI-004** MUST: Incoming c_char pointers MUST be checked for null before dereferencing. +- **R-FFI-005** SHOULD: CStr SHOULD be converted to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements. +- **R-FFI-006** MUST: The free_c_string function MUST be implemented as: unsafe { CString::from_raw(ptr) } to reclaim and drop memory. +- **R-FFI-007** SHOULD: Result return types with error codes mapped to C-compatible integers SHOULD be used for validation failures. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern "C" functions accepting c_char pointers use CStr::from_ptr for validation +- All extern "C" functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- Null pointer checks are present before all CStr::from_ptr calls +- free_c_string is implemented using unsafe { CString::from_raw(ptr) } + + +Claude Code MUST NOT skip or defer verification. All FFI functions must pass automated grep/pattern matching and clippy linting before acceptance. Security team review is mandatory for all FFI boundary changes. Violations in cryptographic code paths trigger security incident review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-generated-bindings-specify-95a4.md b/.actual/rules/cross-cutting-generated-bindings-specify-95a4.md new file mode 100644 index 000000000000..5ab65725fbcc --- /dev/null +++ b/.actual/rules/cross-cutting-generated-bindings-specify-95a4.md @@ -0,0 +1,30 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Generated Bindings Specify + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs) responsible for generating language bindings, test fixtures and mock data used for cryptographic operation testing, and the public API surface exposed through FFI to managed C# code. + +### Rules + +- **R-FFI-001** MUST: Generated C# bindings MUST specify a consistent namespace (e.g., Bit.RustSDK) and public class accessibility for consumer access. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Verify test fixtures use clear naming conventions +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated bindings exist in expected location +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure +- Generated C# code compiles successfully against the C# codebase + + +Claude Code MUST NOT skip or defer verification. Automated CI checks MUST verify that build.rs successfully generates C# bindings and that generated files compile. Code review MUST check for proper use of csbindgen configuration and test fixture naming conventions. Static analysis tools MUST scan for usage of test constants in non-test production code paths. Violations result in CI build failures, code review rejection, or security review escalation as appropriate. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-hardcoded-rsa-private-4685.md b/.actual/rules/cross-cutting-hardcoded-rsa-private-4685.md new file mode 100644 index 000000000000..6b123e2c60f4 --- /dev/null +++ b/.actual/rules/cross-cutting-hardcoded-rsa-private-4685.md @@ -0,0 +1,35 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Hardcoded Rsa Private + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-HARDCODED-RSA-001** MUST: All hardcoded RSA private keys intended for testing MUST use the naming pattern `_FAKE_RSA_KEY_N` where N is a sequential integer starting from 0. +- **R-HARDCODED-RSA-002** MUST: All `_FAKE_RSA_KEY_*` constants MUST be defined in a dedicated test fixtures module (e.g., `rsa_keys.rs`) with `const` visibility and PEM PKCS#8 format. +- **R-HARDCODED-RSA-003** MUST: No references to `_FAKE_RSA_KEY_*` constants SHALL exist outside `#[cfg(test)]` blocks or test-only modules. +- **R-HARDCODED-RSA-004** MUST: Each fake key constant MUST include inline documentation explaining its intended test scenario. +- **R-HARDCODED-RSA-005** SHOULD: CI pipeline SHOULD include automated checks that fail builds if production code references test key constants. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key constants are valid PEM-encoded PKCS#8 keys +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- All 5 fake RSA keys (0-4) are present and valid + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for cryptographic test fixtures in the Rust SDK. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-action-methods-a5bd.md b/.actual/rules/cross-cutting-http-action-methods-a5bd.md new file mode 100644 index 000000000000..bd1d25e60fd6 --- /dev/null +++ b/.actual/rules/cross-cutting-http-action-methods-a5bd.md @@ -0,0 +1,31 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Http Action Methods + +These rules are ALWAYS ACTIVE for all HTTP action methods in API controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes, verified through unit tests using the Xunit framework. + +### Rules + +- **R-AUTH-001** MUST: All HTTP action methods (decorated with HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST have method-level authorization attributes from Microsoft.AspNetCore.Authorization or custom authorization implementations. + +### Verify + +```bash +# Count invocations of authorization test helper across test projects +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run authorization-specific unit tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes applied to controllers +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- CI pipeline executes authorization verification tests and fails builds when attributes are missing +- Pull request checks require passing unit tests including authorization verification + + +Claude Code MUST NOT skip or defer verification of authorization attributes on HTTP action methods. All violations identified by unit test execution MUST be resolved before code proceeds to production. Exceptions require explicit [AllowAnonymous] attributes with documented security review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-client-configurations-b862.md b/.actual/rules/cross-cutting-http-client-configurations-b862.md new file mode 100644 index 000000000000..a4d2368d062a --- /dev/null +++ b/.actual/rules/cross-cutting-http-client-configurations-b862.md @@ -0,0 +1,29 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Http Client Configurations + +These rules are ALWAYS ACTIVE for all HTTP client implementations across service-oriented architecture integrations with external APIs, distributed system components, and cross-language FFI boundaries in both C# and Rust codebases. + +### Rules + +- **R-HTTP-001** SHOULD: HTTP client configurations SHOULD include timeout policies, retry logic, and circuit breaker patterns for resilient external service integration. + +### Verify + +```bash +# Count AddHttpClient registrations in C# services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Count direct HttpClient instantiations outside tests +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Count safe FFI string marshaling patterns in Rust +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns outside test contexts is mandatory. Code review checklist requiring HTTP client registration verification for new external service integrations is mandatory. Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios is mandatory. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-clients-registered-2dbc.md b/.actual/rules/cross-cutting-http-clients-registered-2dbc.md new file mode 100644 index 000000000000..b3fda74b5e3c --- /dev/null +++ b/.actual/rules/cross-cutting-http-clients-registered-2dbc.md @@ -0,0 +1,29 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Http Clients Registered + +These rules are ALWAYS ACTIVE for all HTTP client implementations across C# services and Rust FFI boundaries integrating with external third-party APIs, distributed system components, and remote data sources. + +### Rules + +- **R-HTTP-001** MUST: HTTP clients MUST be registered through dependency injection containers to enable proper lifecycle management and connection pooling. + +### Verify + +```bash +# Count AddHttpClient registrations in C# services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Count direct HttpClient instantiations outside tests (should be zero in production) +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Verify Rust FFI boundaries use safe string marshaling +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + + +Clause Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns outside test contexts is mandatory. Code review checklist must verify HTTP client registration for all new external service integrations. CI pipeline MUST fail on detection of direct HttpClient instantiation in production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-clients-that-7859.md b/.actual/rules/cross-cutting-http-clients-that-7859.md new file mode 100644 index 000000000000..68285ff97fb5 --- /dev/null +++ b/.actual/rules/cross-cutting-http-clients-that-7859.md @@ -0,0 +1,33 @@ +# Establish HTTP Client Boundaries for External Service Integration: Http Clients That + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, and identity providers. + +### Rules + +- **R-HTTP-001** MUST: HTTP clients that interact with user-supplied URLs MUST include SSRF protection through AddSsrfProtection() handler registration. +- **R-HTTP-002** MUST: All HTTP clients MUST be created through IHttpClientFactory via services.AddHttpClient() or services.AddHttpClient(name) registrations in Startup.cs, never through direct `new HttpClient()` instantiation. +- **R-HTTP-003** SHOULD: Use named clients with services.AddHttpClient(name) to enable configuration isolation and handler pipeline customization per external service. +- **R-HTTP-004** SHOULD: Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are registered for user-facing clients +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct `new HttpClient()` instantiations outside documented legacy exceptions (EXC-001, EXC-002). +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline. +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services. +- All AddHttpClient registrations are centralized in Startup.cs ConfigureServices method. + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations MUST pass the verify commands above. Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment. Direct HttpClient instantiation outside documented exceptions blocks pull request merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-endpoint-methods-6d08.md b/.actual/rules/cross-cutting-http-endpoint-methods-6d08.md new file mode 100644 index 000000000000..83034eb8e4a6 --- /dev/null +++ b/.actual/rules/cross-cutting-http-endpoint-methods-6d08.md @@ -0,0 +1,34 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Http Endpoint Methods + +These rules are ALWAYS ACTIVE for all HTTP controller classes and endpoint methods in the service API layer. + +### Rules + +- **R-CQSA-001** MUST: HTTP endpoint methods MUST map to command or query interface methods rather than performing direct data access or persistence operations. +- **R-CQSA-002** MUST: All API controller action methods MUST use async Task signatures and await command/query interface methods. +- **R-CQSA-003** MUST: Controllers MUST inject command/query interfaces via constructor dependency injection rather than accessing DbContext or data access layers directly. +- **R-CQSA-004** SHOULD: Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (e.g., SceneExecutionException). +- **R-CQSA-005** SHOULD: Add structured logging at API boundary entry points using ILogger with semantic context for operation traceability. + +### Verify + +```bash +# Verify all controller action methods use async Task pattern +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controller classes +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files with async/await patterns +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access. +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments). +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar). +- Controllers inject command/query interfaces through constructor dependency injection without direct data access layer references. + + +Clause Code MUST NOT skip or defer verification. All violations MUST be caught during code review and static analysis before merge. Pull requests with direct data access in controllers are rejected with reference to this ADR. Static analysis violations block CI pipeline until resolved or explicitly exempted with documented justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-request-headers-a358.md b/.actual/rules/cross-cutting-http-request-headers-a358.md new file mode 100644 index 000000000000..8ca0078704d9 --- /dev/null +++ b/.actual/rules/cross-cutting-http-request-headers-a358.md @@ -0,0 +1,30 @@ +# Establish HTTP Client Boundaries for External Service Integration: Http Request Headers + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, identity providers, and SSO configuration endpoints. + +### Rules + +- **R-HTTP-001** SHOULD: HTTP request headers (e.g., UserAgent, Accept) SHOULD be explicitly configured when external services require specific header values for routing or identification. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are present +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- HTTP request headers are explicitly configured in client registrations via services.AddHttpClient() for external services requiring specific header values + + +Claude Code MUST NOT skip or defer verification. All HTTP client registrations MUST be reviewed for explicit header configuration and SSRF protection before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-requests-scim-d271.md b/.actual/rules/cross-cutting-http-requests-scim-d271.md new file mode 100644 index 000000000000..e8c7506cabd6 --- /dev/null +++ b/.actual/rules/cross-cutting-http-requests-scim-d271.md @@ -0,0 +1,31 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Http Requests Scim + +These rules are ALWAYS ACTIVE for all SCIM API integration test files that handle HTTP request/response serialization, test authentication infrastructure, and Entity Framework data persistence operations. + +### Rules + +- **R-SCIM-001** SHOULD: HTTP requests to SCIM endpoints SHOULD include System.Net.Mime content type headers. + +### Verify + +```bash +# Verify System.Text.Json is used for serialization in SCIM tests +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify data persistence uses DatabaseContext.SaveChanges pattern +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify test authentication handlers use System.Security.Claims +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- HTTP requests include appropriate Content-Type headers via System.Net.Mime +- JsonSerializerOptions are configured with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema + + +Claude Code MUST NOT skip or defer verification. All SCIM integration test changes must be reviewed against these rules. Pull requests introducing alternative serializers require architecture review. Tests bypassing DatabaseContext.SaveChanges must document rationale in comments. Non-compliant test code must be flagged in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-http-response-types-74bf.md b/.actual/rules/cross-cutting-http-response-types-74bf.md new file mode 100644 index 000000000000..9320eb7ef5a5 --- /dev/null +++ b/.actual/rules/cross-cutting-http-response-types-74bf.md @@ -0,0 +1,31 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Http Response Types + +These rules are ALWAYS ACTIVE for all ASP.NET Core minimal API endpoints, MVC controller action results, custom HTTP result types, and integration test HTTP client interactions. + +### Rules + +- **R-IRESULT-001** MUST: HTTP response types MUST implement IResult interface to ensure compatibility with ASP.NET Core endpoint execution pipeline. + +### Verify + +```bash +# Verify all custom HTTP result types implement IResult +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration tests use Server HTTP methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result types are sealed classes with internal constructors and readonly fields for wrapped instances +- Factory methods or extension methods are used for creating custom results rather than public constructors + + +Clause Code MUST NOT skip or defer verification. All custom result types must be scanned for IResult implementation. All endpoint handlers must be reviewed for direct HttpContext.Response usage. All integration tests must use Server HTTP methods. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-implementation-suppress-specific-c43d.md b/.actual/rules/cross-cutting-implementation-suppress-specific-c43d.md new file mode 100644 index 000000000000..a03c53250e7a --- /dev/null +++ b/.actual/rules/cross-cutting-implementation-suppress-specific-c43d.md @@ -0,0 +1,38 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Implementation Suppress Specific + +These rules are ALWAYS ACTIVE for all implementations of IPushNotificationService interface, push notification processing logic handling Bit.Core.NotificationCenter.Entities, validation logic for notification IDs and status IDs, and runtime quality gates for notification state verification. + +### Rules + +- **R-PUSH-001** MAY: Implementation MAY suppress specific static analysis warnings (pragma warning disable) when the warning conflicts with the established logging quality gate pattern. +- **R-PUSH-002** MUST: Use ILogger interface with structured logging templates in the format: `logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id)` +- **R-PUSH-003** MUST: Apply the logging pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities. +- **R-PUSH-004** MUST: Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern. +- **R-PUSH-005** SHOULD: Implement log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform. +- **R-PUSH-006** MUST NOT: Apply warning-level logging to successful notification processing (use Info or Debug levels instead). +- **R-PUSH-007** MUST NOT: Use warning-level logging for system failures or exceptions (use Error level instead). +- **R-PUSH-008** MAY: Exception EXC-001 permits omitting warning-level logging in high-frequency notification processing paths where such logging would create excessive log volume, provided alternative observability mechanisms are documented. + +### Verify + +```bash +# Verify all invalid notification ID scenarios log warning-level events with structured NotificationId parameter +grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' + +# Verify all invalid notification status ID scenarios log warning-level events +grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' + +# Verify pragma warning disable directives are present and documented +find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; +``` + +**Accept when:** +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate +- No warning-level logging is applied to successful notification processing +- No warning-level logging is applied to system failures or exceptions + + +Claude Code MUST NOT skip or defer verification. Code review rejection is required if validation failures lack warning-level logging with structured parameters. CI pipeline warnings must be issued if push notification services are modified without corresponding logging verification. Quarterly audits of pragma warning suppressions are mandatory to ensure they remain justified and documented. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-implementations-use-resource-551e.md b/.actual/rules/cross-cutting-implementations-use-resource-551e.md new file mode 100644 index 000000000000..13fe031f6bc2 --- /dev/null +++ b/.actual/rules/cross-cutting-implementations-use-resource-551e.md @@ -0,0 +1,29 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Implementations Use Resource + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +### Rules + +- **R-FFI-001** MAY: Implementations MAY use resource pools (e.g., RSA_POOL) to manage expensive cryptographic objects across FFI calls. + +### Verify + +```bash +# Check that all FFI functions accepting c_char pointers include CStr::from_ptr validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify at least 5 fake RSA key fixtures exist for testing +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Confirm RSA key validation tests pass +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST pass before accepting this rule as satisfied. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-include-structured-contextual-052d.md b/.actual/rules/cross-cutting-include-structured-contextual-052d.md new file mode 100644 index 000000000000..2d2276c4c546 --- /dev/null +++ b/.actual/rules/cross-cutting-include-structured-contextual-052d.md @@ -0,0 +1,29 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Include Structured Contextual + +These rules are ALWAYS ACTIVE for controller methods decorated with [Authorize] or custom authorization requirements, operations involving external HTTP clients (IHttpClientFactory usage), third-party service integrations (Stripe, external APIs), and multi-step operations where partial success is acceptable. + +### Rules + +- **R-LOGGING-001** MUST: Include structured contextual parameters in log messages using named placeholders (e.g., {ProviderId}, {RequestUri}) that correspond to method arguments when logging external service failures. + +### Verify + +```bash +# Find LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find catch blocks with LogError in API and Admin namespaces +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-specific tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' +``` + +**Accept when:** +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + + +Claude Code MUST NOT skip or defer verification. All controller methods integrating with external services must include structured contextual parameters in log messages before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-infrastructure-services-registered-9d84.md b/.actual/rules/cross-cutting-infrastructure-services-registered-9d84.md new file mode 100644 index 000000000000..ba3801ff4a80 --- /dev/null +++ b/.actual/rules/cross-cutting-infrastructure-services-registered-9d84.md @@ -0,0 +1,31 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Infrastructure Services Registered + +These rules are ALWAYS ACTIVE for all application startup, factory, and service configuration files that register infrastructure services with the dependency injection container. + +### Rules + +- **R-INFRA-001** MUST: Infrastructure services MUST be registered in the dependency injection container using AddSingleton, AddScoped, or AddTransient based on lifecycle requirements. + +### Verify + +```bash +# Check for active use of dependency injection patterns +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration is present +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Find test factory classes that configure service registrations +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments +- All external dependencies are registered via interface abstractions (e.g., IMailService) rather than concrete implementations +- Test environments use factory classes that override service registrations with test doubles + + +Claude Code MUST NOT skip or defer verification. Service registration patterns MUST be validated at code review time and integration test execution time to ensure proper dependency isolation and service resolution. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-input-validation-ffi-32ec.md b/.actual/rules/cross-cutting-input-validation-ffi-32ec.md new file mode 100644 index 000000000000..43e8734732ac --- /dev/null +++ b/.actual/rules/cross-cutting-input-validation-ffi-32ec.md @@ -0,0 +1,34 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Input Validation Ffi + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept c_char pointers or handle cryptographic material across C interop boundaries. + +### Rules + +- **R-FFI-001** MUST: Input validation at FFI boundaries MUST occur before any cryptographic operations (cipher generation, RSA key operations, SymmetricCryptoKey usage). +- **R-FFI-002** MUST: All public FFI functions accepting c_char pointers MUST use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing. +- **R-FFI-003** MUST: All FFI functions returning strings MUST use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with corresponding free functions. +- **R-FFI-004** SHOULD: Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements. +- **R-FFI-005** SHOULD: Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, and empty strings. + +### Verify + +```bash +# Count FFI functions using CStr/CString patterns +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify all public FFI functions use proper validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI test coverage for validation scenarios +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- No raw c_char pointer dereferencing occurs without CStr validation in cryptographic code paths + + +Claude Code MUST NOT skip or defer verification. All FFI functions handling cryptographic material require explicit validation before processing. Violations must be flagged for immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-test-factories-1764.md b/.actual/rules/cross-cutting-integration-test-factories-1764.md new file mode 100644 index 000000000000..e3d483417e56 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-test-factories-1764.md @@ -0,0 +1,41 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Integration Test Factories + +These rules are ALWAYS ACTIVE for all SCIM service authentication handlers, authorization policies, and integration test factories within the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization(). +- **R-SCIM-AUTH-002** MUST: Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-AUTH-003** MUST: Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim'). +- **R-SCIM-AUTH-004** MUST: Isolate test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-AUTH-005** MUST: Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic. +- **R-SCIM-AUTH-006** MAY: Integration test factories MAY override production authentication with test-specific handlers that bypass credential validation for controlled test environments. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy configuration +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers are isolated +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline +- ApiKeyAuthenticationHandler properly validates credentials and populates scope claims +- Organizational context claims are included in authentication tickets for multi-tenant support + + +Claude Code MUST NOT skip or defer verification. All SCIM authentication configuration changes require verification that ApiKeyAuthenticationOptions.DefaultScheme is maintained, scope claims are properly enforced, and test handlers remain isolated from production code. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-test-projects-bc7e.md b/.actual/rules/cross-cutting-integration-test-projects-bc7e.md new file mode 100644 index 000000000000..41520b2651d6 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-test-projects-bc7e.md @@ -0,0 +1,39 @@ +# Adopt Test Authentication Scheme for Integration Testing: Integration Test Projects + +These rules are ALWAYS ACTIVE for all integration test projects and test factory classes that configure authentication middleware for the ASP.NET Core authentication pipeline. + +### Rules + +- **R-TESTAUTH-001** MUST: Integration test projects MUST call AddAuthentication() to register authentication schemes in the service collection. +- **R-TESTAUTH-002** MUST: Test authentication handlers MUST extend AuthenticationHandler with HandleAuthenticateAsync() implementations that return deterministic claims. +- **R-TESTAUTH-003** MUST: Test authentication handlers MUST return AuthenticateResult.Success() with a ClaimsIdentity containing test-appropriate claims (e.g., ClaimTypes.Name, organization identifiers). +- **R-TESTAUTH-004** MUST: Test authentication schemes MUST be registered only in test environments using environment-specific configuration to prevent accidental deployment to production. +- **R-TESTAUTH-005** SHOULD: Test authentication handlers SHOULD include constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock following ASP.NET Core patterns. +- **R-TESTAUTH-006** SHOULD: Authorization policies SHOULD be configured after authentication registration to ensure policies can evaluate claims provided by test authentication handlers. + +### Verify + +```bash +# Detect AddAuthentication() calls in test projects +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Detect AuthenticationHandler implementations in test code +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Detect HandleAuthenticateAsync implementations +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Detect AuthenticateResult.Success usage in test authentication +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" +``` + +**Accept when:** +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims +- Environment-specific configuration ensures test authentication schemes are only registered in test environments +- Authorization policies are configured after authentication registration in test startup code + + +Claude Code MUST NOT skip or defer verification of these rules. All integration test projects MUST implement test authentication handlers through the ASP.NET Core authentication pipeline to ensure authorization policies are validated without external identity provider dependencies. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-tests-call-f5ec.md b/.actual/rules/cross-cutting-integration-tests-call-f5ec.md new file mode 100644 index 000000000000..19776797b833 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-tests-call-f5ec.md @@ -0,0 +1,35 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Integration Tests Call + +These rules are ALWAYS ACTIVE for all integration tests in the SCIM integration test suite that interact with the DatabaseContext and execute HTTP requests against SCIM endpoints. + +### Rules + +- **R-SCIM-001** MUST: Integration tests MUST call DatabaseContext.SaveChanges() explicitly to persist test data before executing HTTP requests against SCIM endpoints. +- **R-SCIM-002** MUST: Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests. +- **R-SCIM-003** SHOULD: Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order. +- **R-SCIM-004** SHOULD: Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data. +- **R-SCIM-005** SHOULD: Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests. +- **R-SCIM-006** SHOULD: Batch related entity creation and call SaveChanges once per logical setup phase to avoid performance degradation. + +### Verify + +```bash +# Verify SaveChanges calls in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Count async HTTP operations +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify test authentication configuration +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- No DatabaseContext usage patterns exist without corresponding SaveChanges calls in test setup phases + + +Clause Code MUST NOT skip or defer verification of SaveChanges patterns in integration tests. All pull requests modifying SCIM integration tests MUST be reviewed for explicit SaveChanges calls before HTTP operations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-tests-connect-758d.md b/.actual/rules/cross-cutting-integration-tests-connect-758d.md new file mode 100644 index 000000000000..1c1d82b7af99 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-tests-connect-758d.md @@ -0,0 +1,41 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Integration Tests Connect + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses, including password grant, SSO authorization code flow, and trusted device encryption scenarios. + +### Rules + +- **R-OAUTH-001** MUST: Integration tests for /connect/token endpoints MUST use System.Text.Json for parsing and validating JSON response structures. +- **R-OAUTH-002** MUST: Complex JSON response objects MUST be validated with JsonValueKind.Object assertions before property extraction using GetProperty() methods. +- **R-OAUTH-003** MUST: Authentication failure tests MUST validate specific error message content using Assert.Equal with explicit expected error strings (e.g., 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device'). +- **R-OAUTH-004** MUST: Token requests MUST be constructed using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information). +- **R-OAUTH-005** MUST: SSO and trusted device encryption flow tests MUST validate userDecryptionOptions object presence and structure in addition to standard token response properties. +- **R-OAUTH-006** SHOULD: Shared helper methods for common JSON assertion patterns SHOULD be created and centralized to reduce duplication across test files. +- **R-OAUTH-007** SHOULD: JSON parsing logic SHOULD be encapsulated in test utility classes to isolate dependency on System.Text.Json API surface. + +### Verify + +```bash +# Verify System.Text.Json usage in integration tests +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Verify error message assertions in authentication failure tests +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run integration tests for OAuth token endpoints +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place +- Token requests are constructed using FormUrlEncodedContent with required OAuth parameters +- SSO and trusted device encryption tests validate userDecryptionOptions object structure + + +Clause Code MUST NOT skip or defer verification. Code review of integration test pull requests MUST check for System.Text.Json usage and JsonValueKind assertions. CI pipeline execution of Identity.IntegrationTest suite MUST validate test pass rates. Pull requests introducing integration tests without proper JSON validation patterns MUST be flagged in code review. Test failures due to missing or incorrect JSON assertions MUST block merge until corrected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-tests-use-d5ac.md b/.actual/rules/cross-cutting-integration-tests-use-d5ac.md new file mode 100644 index 000000000000..3c792d54957f --- /dev/null +++ b/.actual/rules/cross-cutting-integration-tests-use-d5ac.md @@ -0,0 +1,40 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Integration Tests Use + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses, including password grant, SSO authorization code flow, and trusted device encryption scenarios. + +### Rules + +- **R-OAUTH-001** SHOULD: Integration tests SHOULD use FormUrlEncodedContent with explicit Dictionary for token request parameters including scope, client_id, grant_type, and device information. +- **R-OAUTH-002** MUST: Use System.Text.Json.JsonDocument for parsing HTTP response content from OAuth token endpoints. +- **R-OAUTH-003** MUST: Validate JsonValueKind.Object for complex JSON properties before attempting property extraction using GetProperty() methods. +- **R-OAUTH-004** MUST: For authentication failure tests, use Assert.Equal with explicit expected error message strings (e.g., 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device'). +- **R-OAUTH-005** MUST: For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties. +- **R-OAUTH-006** SHOULD: Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods. + +### Verify + +```bash +# Check for System.Text.Json usage in integration test files +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Check for explicit error message assertions +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run integration tests for OAuth token endpoint validation +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place +- FormUrlEncodedContent is used with explicit Dictionary for all token request construction +- userDecryptionOptions object presence and structure are validated in SSO and trusted device encryption flow tests + + +Code review of integration test pull requests MUST verify System.Text.Json usage and JsonValueKind assertions. CI pipeline execution of Identity.IntegrationTest suite MUST validate test pass rates. Static analysis or grep-based checks MUST confirm consistent JSON assertion patterns. Pull requests introducing integration tests without proper JSON validation patterns MUST be flagged in code review. Test failures due to missing or incorrect JSON assertions MUST block merge until corrected. Claude Code MUST NOT skip or defer verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-integration-tests-use-ef0e.md b/.actual/rules/cross-cutting-integration-tests-use-ef0e.md new file mode 100644 index 000000000000..18cecd65af07 --- /dev/null +++ b/.actual/rules/cross-cutting-integration-tests-use-ef0e.md @@ -0,0 +1,35 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Integration Tests Use + +These rules are ALWAYS ACTIVE for ASP.NET Core minimal API endpoints, MVC controller action results, custom HTTP result types, and integration test HTTP client interactions. + +### Rules + +- **R-IRESULT-001** MUST: Integration tests MUST use Server HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) rather than direct HttpContext construction. +- **R-IRESULT-002** MUST: Custom HTTP result types MUST implement IResult and delegate ExecuteAsync to inner framework results. +- **R-IRESULT-003** MUST: Endpoint handlers MUST NOT perform direct HttpContext.Response manipulation outside approved middleware exceptions (EXC-001). +- **R-IRESULT-004** SHOULD: Custom result types SHOULD be implemented as sealed classes wrapping framework results with internal constructors to control instantiation. +- **R-IRESULT-005** SHOULD: Custom result wrappers SHOULD use readonly fields for inner result storage and delegate all interface members to the wrapped instance. +- **R-IRESULT-006** SHOULD: Result instantiation SHOULD be exposed through factory methods or extension methods rather than public constructors. + +### Verify + +```bash +# Verify IResult interface implementation in result types +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns (exclude direct HttpContext.Response.WriteAsync) +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration tests use Server HTTP methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result wrappers follow sealed class pattern with internal constructors and readonly field delegation + + +Claude Code MUST NOT skip or defer verification. All three verify commands MUST execute successfully before accepting changes to result types or integration tests. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-internal-controller-actions-e0ea.md b/.actual/rules/cross-cutting-internal-controller-actions-e0ea.md new file mode 100644 index 000000000000..18ae6e065b2e --- /dev/null +++ b/.actual/rules/cross-cutting-internal-controller-actions-e0ea.md @@ -0,0 +1,30 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Internal Controller Actions + +These rules are ALWAYS ACTIVE for all internal API controller actions in the AdminConsole and Admin controllers that manage organization resources or require authenticated access. + +### Rules + +- **R-AUTHZ-001** MUST: All internal API controller actions that manage organization resources MUST apply authorization attributes (e.g., `[Authorize]`) to enforce access control at the action level. + +### Verify + +```bash +# Count authorization attributes on internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Verify public action methods have authorization attributes +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific unit tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes +- Public endpoints are explicitly marked with `[AllowAnonymous]` attribute and include security rationale in code comments + + +Claude Code MUST NOT skip or defer verification. All internal API controller actions must be scanned for authorization attributes before accepting changes. Missing authorization on organization-scoped endpoints is a security violation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-json-serialization-use-2eb1.md b/.actual/rules/cross-cutting-json-serialization-use-2eb1.md new file mode 100644 index 000000000000..3adb72ba5406 --- /dev/null +++ b/.actual/rules/cross-cutting-json-serialization-use-2eb1.md @@ -0,0 +1,32 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Json Serialization Use + +These rules are ALWAYS ACTIVE for all SCIM API integration test projects, ScimApplicationFactory and related test infrastructure, HTTP request/response serialization for SCIM v2 endpoints, and Entity Framework DatabaseContext operations for SCIM resources. + +### Rules + +- **R-SCIM-JSON-001** MUST: JSON serialization MUST use System.Text.Encodings.Web for proper encoding of special characters in SCIM data. + +### Verify + +```bash +# Verify System.Text.Json is used in SCIM integration tests +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify data persistence uses DatabaseContext.SaveChanges pattern +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify test authentication handlers use System.Security.Claims +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- JsonSerializerOptions are configured with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- GetStringContent helper method wraps serialized JSON with correct Content-Type headers +- DatabaseContext is properly scoped per test to avoid state leakage between test cases + + +Clause Code MUST NOT skip or defer verification. All SCIM integration test changes require code review confirmation of System.Text.Json usage and DatabaseContext.SaveChanges pattern compliance. Static analysis scanning for System.Text.Json usage in test projects is mandatory. CI pipeline verification that tests use ScimApplicationFactory pattern is required. Pull requests introducing alternative serializers in SCIM tests require architecture review. Tests bypassing DatabaseContext.SaveChanges must document rationale in comments. Non-compliant test code flagged in code review with request for alignment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-key-generation-functions-aca2.md b/.actual/rules/cross-cutting-key-generation-functions-aca2.md new file mode 100644 index 000000000000..b8f11e1be97e --- /dev/null +++ b/.actual/rules/cross-cutting-key-generation-functions-aca2.md @@ -0,0 +1,46 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Key Generation Functions + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in `util/RustSdk/rust/src/lib.rs` that handle cryptographic key material, including public key generation APIs and cipher/RSA key data structures exposed across FFI boundaries. + +### Rules + +- **R-FFI-KGF-001** MUST: Key generation functions (`generate_user_keys`, `generate_organization_keys`, `generate_user_organization_key`) MUST expose public contracts (pub) at the FFI boundary with memory management functions (`free_c_string`). +- **R-FFI-KGF-002** MUST: All data structures crossing FFI boundaries MUST use `#[repr(C)]` attribute to ensure stable memory layout. +- **R-FFI-KGF-003** MUST: All CStr::from_ptr calls MUST be wrapped in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-FFI-KGF-004** MUST: All public FFI functions handling key material MUST use std::ffi types (c_char, CStr, CString) with explicit input validation. +- **R-FFI-KGF-005** MUST: Memory ownership semantics MUST be documented in FFI function comments, specifying which side (Rust or C) owns allocated memory and when `free_c_string` must be called. +- **R-FFI-KGF-006** SHOULD: Mock implementations SHOULD be provided for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations. +- **R-FFI-KGF-007** SHOULD: Mock traits (e.g., CipherOps, RsaKeyOps) SHOULD be defined to allow both production and test implementations, using dependency injection or feature flags to select implementations. +- **R-FFI-KGF-008** SHOULD: Integration tests using real cryptographic operations SHOULD be maintained alongside unit tests with mocks to verify dual implementation correctness. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Verify #[repr(C)] on FFI-crossing structures +grep -B1 'pub struct' util/RustSdk/rust/src/lib.rs | grep -c '#\[repr(C)\]' + +# Run tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 + +# Verify memory management functions exist +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings +- All data structures crossing FFI boundaries use #[repr(C)] attribute +- CStr::from_ptr calls are wrapped in unsafe blocks with null pointer checks and UTF-8 validation +- Memory ownership semantics are documented in FFI function comments +- Both unit tests (with mocks) and integration tests (with real crypto) pass successfully + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if FFI functions lack required validation or memory management functions. Pull requests adding new FFI entry points MUST require security team approval. Runtime panics in FFI code MUST trigger incident review and post-mortem analysis. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-key-management-modules-aaf3.md b/.actual/rules/cross-cutting-key-management-modules-aaf3.md new file mode 100644 index 000000000000..67a64a389172 --- /dev/null +++ b/.actual/rules/cross-cutting-key-management-modules-aaf3.md @@ -0,0 +1,44 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Key Management Modules + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material, including public key generation APIs and cipher/RSA key data structures exposed across FFI boundaries. + +### Rules + +- **R-FFI-KM-001** MUST: All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation at the language boundary. +- **R-FFI-KM-002** MUST: All CStr::from_ptr calls are wrapped in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-FFI-KM-003** MUST: Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings, with clear ownership semantics. +- **R-FFI-KM-004** MUST: Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout. +- **R-FFI-KM-005** SHOULD: Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations. +- **R-FFI-KM-006** SHOULD: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly. +- **R-FFI-KM-007** MAY: Key management modules MAY use std::collections::HashSet for tracking key identifiers or managing key lifecycle state. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Run tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 + +# Verify #[repr(C)] on FFI-crossing structures +grep -B1 'pub struct' util/RustSdk/rust/src/lib.rs | grep -c '#\[repr(C)\]' + +# Check for unsafe blocks around CStr::from_ptr +grep -A2 'CStr::from_ptr' util/RustSdk/rust/src/lib.rs | grep -c 'unsafe' +``` + +**Accept when:** +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings +- All data structures crossing FFI boundaries are annotated with #[repr(C)] +- All CStr::from_ptr calls are protected by unsafe blocks with null pointer and UTF-8 checks +- Integration tests using real cryptographic operations pass alongside unit tests with mocks + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if FFI functions lack required validation or memory management functions. Pull requests adding new FFI entry points MUST require security team approval. Runtime panics in FFI code MUST trigger incident review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-log-entries-failures-fb74.md b/.actual/rules/cross-cutting-log-entries-failures-fb74.md new file mode 100644 index 000000000000..89f287d4cada --- /dev/null +++ b/.actual/rules/cross-cutting-log-entries-failures-fb74.md @@ -0,0 +1,35 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Entries Failures + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with `[Authorize]` or custom authorization attributes, controller actions that invoke external services after authorization checks, admin and provider management endpoints handling sensitive resource operations, and exception handlers within authorized action methods. + +### Rules + +- **R-LOGAUTH-001** MUST: Log entries for failures in authorized contexts MUST include structured parameters for resource identifiers (e.g., `{ProviderId}`, `{UserId}`) using named placeholders, not string interpolation. +- **R-LOGAUTH-002** MUST: Inject `ILogger` via constructor dependency injection in all controllers with `[Authorize]` attributes or custom authorization requirements. +- **R-LOGAUTH-003** MUST: Use `LogError(exception, message, structuredParams)` pattern for all catch blocks within authorized actions, ensuring the exception object is the first parameter. +- **R-LOGAUTH-004** MUST: Define structured parameter names as constants (e.g., `const string ProviderIdParam = "{ProviderId}"`) to ensure consistency across log statements. +- **R-LOGAUTH-005** MUST NOT: Log sensitive data (tokens, passwords, PII, credit card information) in structured parameters within authorized contexts. +- **R-LOGAUTH-006** SHOULD: Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers. + +### Verify + +```bash +# Check for [Authorize] attributes without ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters in controller files +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in log statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with `[Authorize]` attributes inject `ILogger` and have no grep matches for missing logger injection. +- All `LogError` calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches. +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters. +- All new authorized endpoints include structured logging with resource identifiers in catch blocks and failure paths. + + +Claude Code MUST NOT skip or defer verification. All controllers with authorization attributes MUST be checked for proper ILogger injection and structured logging patterns. Static analysis violations MUST be resolved or explicitly suppressed with justification before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-log-entries-not-bf81.md b/.actual/rules/cross-cutting-log-entries-not-bf81.md new file mode 100644 index 000000000000..458777d77cfc --- /dev/null +++ b/.actual/rules/cross-cutting-log-entries-not-bf81.md @@ -0,0 +1,34 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Entries Not + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes, controller actions that invoke external services after authorization checks, and admin and provider management endpoints handling sensitive resource operations. + +### Rules + +- **R-AUTHLOG-001** MUST NOT: Log entries MUST NOT include sensitive authentication tokens, passwords, payment details, or personally identifiable information beyond resource identifiers. +- **R-AUTHLOG-002** MUST: Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements. +- **R-AUTHLOG-003** MUST: Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter. +- **R-AUTHLOG-004** SHOULD: Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements. +- **R-AUTHLOG-005** SHOULD: Include resource identifiers (ProviderId, RequestUri, etc.) as structured parameters in all log statements within authorized contexts to enable correlation with authorization decisions. +- **R-AUTHLOG-006** MAY: Request exception from architecture review board for high-frequency endpoints where structured logging would create excessive log volume, with documented sampling strategy. + +### Verify + +```bash +# Check for [Authorize] attributes without ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in logging statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + + +Clause Code MUST NOT skip or defer verification. All three verify commands must pass before accepting changes to authorized controller endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-log-exceptions-external-4360.md b/.actual/rules/cross-cutting-log-exceptions-external-4360.md new file mode 100644 index 000000000000..22581c1219e8 --- /dev/null +++ b/.actual/rules/cross-cutting-log-exceptions-external-4360.md @@ -0,0 +1,29 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Log Exceptions External + +These rules are ALWAYS ACTIVE for controller methods decorated with [Authorize] or custom authorization requirements, operations involving external HTTP clients (IHttpClientFactory usage), and third-party service integrations (Stripe, external APIs) where partial success is acceptable. + +### Rules + +- **R-EX-001** MUST: Log exceptions from external service calls using ILogger.LogError with the exception object as the first parameter. + +### Verify + +```bash +# Find LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find catch blocks that log errors in API and Admin namespaces +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-specific tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' +``` + +**Accept when:** +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern (e.g., {ProviderId}, {RequestUri}) + + +Claude Code MUST NOT skip or defer verification. All external service failure logging MUST include exception objects and structured contextual parameters. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-log-messages-describe-7507.md b/.actual/rules/cross-cutting-log-messages-describe-7507.md new file mode 100644 index 000000000000..2e8db964fa77 --- /dev/null +++ b/.actual/rules/cross-cutting-log-messages-describe-7507.md @@ -0,0 +1,39 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Log Messages Describe + +These rules are ALWAYS ACTIVE for controller methods decorated with `[Authorize]` or custom authorization requirements, operations involving external HTTP clients (`IHttpClientFactory` usage), and third-party service integrations (Stripe, external APIs) where partial success is acceptable. + +### Rules + +- **R-LOG-001** SHOULD: Log messages should describe the failure context and the state of the primary operation (e.g., 'Database was updated successfully' when Stripe sync fails). +- **R-LOG-002** MUST: Use `ILogger.LogError` with exception objects and at least one structured parameter for external service failures in non-critical paths. +- **R-LOG-003** MUST: Use named placeholders in log message templates that match parameter names (e.g., `_logger.LogError(ex, 'Failed for {ProviderId}', providerId)`). +- **R-LOG-004** MUST: Wrap external service calls in try-catch blocks when the operation is non-critical to the primary request flow. +- **R-LOG-005** SHOULD: Include contextual parameters such as entity IDs and URIs in structured logging to enable log aggregation and querying. +- **R-LOG-006** MUST NOT: Log sensitive data (tokens, API keys) in exception messages or parameters; use log scrubbing middleware where necessary. + +### Verify + +```bash +# Find LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find try-catch blocks around external service calls with LogError +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-specific tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +# Verify no string concatenation in LogError calls +grep -r 'LogError.*+' --include='*.cs' src/ | grep -v '//' +``` + +**Accept when:** +- All controller methods with external service calls use `ILogger.LogError` with exception object and at least one structured parameter. +- External service failures in non-critical paths are caught and logged without propagating to the client. +- Log messages include contextual parameters using named placeholders matching the structured logging pattern. +- No sensitive data (tokens, API keys) appears in logged exception messages or parameters. +- Partial success states are documented in log messages (e.g., 'Database updated successfully' when synchronization fails). + + +Claude Code MUST NOT skip or defer verification. All controller methods integrating with external services MUST include structured logging with contextual parameters. Code review MUST enforce this pattern before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-log-messages-describe-db43.md b/.actual/rules/cross-cutting-log-messages-describe-db43.md new file mode 100644 index 000000000000..2955de53e7d7 --- /dev/null +++ b/.actual/rules/cross-cutting-log-messages-describe-db43.md @@ -0,0 +1,30 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Messages Describe + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC controller files decorated with `[Authorize]` or custom authorization attributes, particularly ProvidersController and HomeController, that invoke external services or handle sensitive resource operations after authorization checks. + +### Rules + +- **R-AUTHLOG-001** SHOULD: Log messages SHOULD describe the operation outcome and context (e.g., 'Failed to update Stripe customer for provider {ProviderId}. Database was updated successfully.') to aid correlation with authorization events + +### Verify + +```bash +# Check for controllers with [Authorize] that lack ILogger injection +grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ + +# Check for LogError calls without structured parameters (missing curly braces) +grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" + +# Check for sensitive parameter names in logging statements +grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" +``` + +**Accept when:** +- All controllers with `[Authorize]` attributes inject `ILogger` via constructor dependency injection +- All `LogError` calls in controller files use structured parameters (contain curly braces) with resource identifiers like `{ProviderId}`, `{RequestUri}`, etc. +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters +- Exception handlers and catch blocks within authorized action methods follow the `LogError(exception, message, structuredParams)` pattern + + +Clause Code MUST NOT skip or defer verification. All three verify commands must pass before accepting a pull request that adds or modifies authorized controller endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-logger-verification-use-7680.md b/.actual/rules/cross-cutting-logger-verification-use-7680.md new file mode 100644 index 000000000000..04a261fe03fc --- /dev/null +++ b/.actual/rules/cross-cutting-logger-verification-use-7680.md @@ -0,0 +1,39 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Logger Verification Use + +These rules are ALWAYS ACTIVE for unit tests in services and commands that include ILogger dependencies, particularly in test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected. + +### Rules + +- **R-LOG-001** MUST: Logger verification MUST use the dependency injection provider pattern (e.g., `sutProvider.GetDependency>()`) to retrieve logger instances in unit tests. +- **R-LOG-002** SHOULD: Apply logger verification to error paths, security events, and operational alerts where log messages are part of the observable contract. +- **R-LOG-003** SHOULD: Use `Received(1)` or `ReceivedWithAnyArgs()` from NSubstitute to verify logger method invocations (LogWarning, LogError, LogInformation). +- **R-LOG-004** SHOULD: Focus logger verification on components in Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging. +- **R-LOG-005** MAY: Extract logger verification into helper methods when multiple tests verify similar logging patterns. +- **R-LOG-006** MAY: Document in test comments when logger verification is intentionally omitted for purely diagnostic logging (Exception EX-001). + +### Verify + +```bash +# Count existing logger verification patterns in test files +grep -r 'GetDependency>()` calls that retrieve logger instances for verification +- Logger verification uses `Received()` or `ReceivedWithAnyArgs()` to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts +- Error paths and operational events in services/commands have corresponding logger verification in their unit tests +- Test comments document exceptions where logger verification is intentionally omitted + + +Claude Code MUST NOT skip or defer verification of logger invocations in unit tests for observability components. Code review checks, CI pipeline unit test execution, and static analysis must confirm adherence to the dependency injection provider pattern and logger verification assertions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-logger-verification-use-910f.md b/.actual/rules/cross-cutting-logger-verification-use-910f.md new file mode 100644 index 000000000000..ba9d9c5492cf --- /dev/null +++ b/.actual/rules/cross-cutting-logger-verification-use-910f.md @@ -0,0 +1,30 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Logger Verification Use + +These rules are ALWAYS ACTIVE for unit tests in services and commands that include ILogger dependencies, particularly in test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected. + +### Rules + +- **R-LOG-001** SHOULD: Logger verification SHOULD use ReceivedWithAnyArgs() when the exact message parameters are not critical to the test assertion. + +### Verify + +```bash +# Count logger dependency retrievals in test files +grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts +- Logger verification focuses on error paths, security events, and operational alerts rather than purely diagnostic logging + + +Claude Code MUST NOT skip or defer verification of logger invocations in unit tests for observability components. Code review checks and CI pipeline validation are mandatory before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-logging-statements-use-3a5d.md b/.actual/rules/cross-cutting-logging-statements-use-3a5d.md new file mode 100644 index 000000000000..32e141d8527b --- /dev/null +++ b/.actual/rules/cross-cutting-logging-statements-use-3a5d.md @@ -0,0 +1,39 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Logging Statements Use + +These rules are ALWAYS ACTIVE for all Redis connection initialization code in distributed cache extensions, particularly in service registration and ConnectionMultiplexer.Connect operations. + +### Rules + +- **R-REDIS-LOG-001** MUST: Wrap all ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions. +- **R-REDIS-LOG-002** MUST: Use ILogger.LogError with the exception as the first parameter and structured logging syntax for contextual parameters. +- **R-REDIS-LOG-003** SHOULD: Include structured logging parameters for cache name and exception details in error log statements (e.g., logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName)). +- **R-REDIS-LOG-004** SHOULD: Inject ILogger instances into service collection extension methods via IServiceProvider or factory patterns. +- **R-REDIS-LOG-005** SHOULD: Avoid string interpolation in logging statements; use named parameters instead for structured logging compatibility. +- **R-REDIS-LOG-006** MAY: Add correlation IDs or request context to error logs for distributed tracing integration. + +### Verify + +```bash +# Find all Redis connection error logging statements +grep -r 'LogError.*Failed to connect to Redis' src/ + +# Count ConnectionMultiplexer.Connect calls wrapped with try-catch +grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' + +# Run cache initialization tests with detailed logging +dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +# Verify no string interpolation in cache-related LogError calls +grep -r 'LogError.*\$"' src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs +``` + +**Accept when:** +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- No string interpolation ($ syntax) is used in logging statements; all parameters are passed as named arguments +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters +- ILogger instances are properly injected or configured before cache service registration + + +Claude Code MUST NOT skip or defer verification. All Redis connection initialization code must be reviewed against these rules during code review and static analysis phases. Violations are treated as build failures in CI pipeline. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-logging-statements-validation-0931.md b/.actual/rules/cross-cutting-logging-statements-validation-0931.md new file mode 100644 index 000000000000..53d135e684a5 --- /dev/null +++ b/.actual/rules/cross-cutting-logging-statements-validation-0931.md @@ -0,0 +1,30 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Logging Statements Validation + +These rules are ALWAYS ACTIVE for all implementations of IPushNotificationService interface, push notification processing logic handling Bit.Core.NotificationCenter.Entities, validation logic for notification IDs and status IDs, and runtime quality gates for notification state verification. + +### Rules + +- **R-PUSH-LOG-001** SHOULD: Logging statements for validation failures SHOULD use structured logging templates with named parameters (e.g., {NotificationId}) rather than string interpolation. + +### Verify + +```bash +# Verify structured logging with NotificationId parameter in invalid notification scenarios +grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' + +# Verify LogWarning usage across IPushNotificationService implementations +grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' + +# Identify pragma warning disable directives in push notification services +find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; +``` + +**Accept when:** +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate +- Logging statements use ILogger.LogWarning with structured templates (e.g., logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id)) + + +Claude Code MUST NOT skip or defer verification. Code review rejection is required if validation failures lack warning-level logging with structured parameters. CI pipeline warnings must be issued if push notification services are modified without corresponding logging verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-memory-allocated-ffi-6520.md b/.actual/rules/cross-cutting-memory-allocated-ffi-6520.md new file mode 100644 index 000000000000..36f0c39712f8 --- /dev/null +++ b/.actual/rules/cross-cutting-memory-allocated-ffi-6520.md @@ -0,0 +1,30 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Memory Allocated Ffi + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers, functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey), and any function marked with #[no_mangle] or extern "C" that accepts string parameters. + +### Rules + +- **R-FFI-001** SHOULD: Memory allocated for FFI string returns SHOULD be freed using a dedicated free_c_string function to prevent leaks. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + + +Claude Code MUST NOT skip or defer verification. All FFI string inputs must be validated using CStr/CString conversion before use in cryptographic operations. Memory allocated for FFI string returns must be freed using the dedicated free_c_string function. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-modules-containing-fake-c0ec.md b/.actual/rules/cross-cutting-modules-containing-fake-c0ec.md new file mode 100644 index 000000000000..17273e6a879f --- /dev/null +++ b/.actual/rules/cross-cutting-modules-containing-fake-c0ec.md @@ -0,0 +1,38 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Modules Containing Fake + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures with `_FAKE_RSA_KEY_*` constants. + +### Rules + +- **R-FAKE-001** MUST: All `_FAKE_RSA_KEY_*` constants MUST be defined in a dedicated test fixtures module (e.g., `rsa_keys.rs`) with `const` visibility and PEM-encoded PKCS#8 format. +- **R-FAKE-002** MUST: No references to `_FAKE_RSA_KEY_*` constants SHALL exist outside `#[cfg(test)]` blocks or test-only modules. +- **R-FAKE-003** SHOULD: Modules containing `_FAKE_RSA_KEY_*` constants SHOULD include automated verification that these constants are never referenced outside test compilation units. +- **R-FAKE-004** SHOULD: Each `_FAKE_RSA_KEY_*` constant SHOULD include inline documentation explaining its intended test scenario (e.g., key rotation, multi-key testing). +- **R-FAKE-005** MUST: CI/CD pipeline MUST include automated checks that fail builds if production code references test key constants. +- **R-FAKE-006** MAY: Non-standard key formats (e.g., SSH format, JWK) for interoperability testing MAY be used under exception EXC-001 with security team approval. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key validation tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- All 5 fake RSA keys (0-4) are present and valid +- Grep verification returns no production references +- Cargo test validation passes + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting changes to cryptographic test fixtures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-multiple-fake-key-4882.md b/.actual/rules/cross-cutting-multiple-fake-key-4882.md new file mode 100644 index 000000000000..f3a7b36626fc --- /dev/null +++ b/.actual/rules/cross-cutting-multiple-fake-key-4882.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Multiple Fake Key + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs), test fixtures, and the public API surface exposed through FFI to managed C# code. + +### Rules + +- **R-FFI-001** MAY: Multiple fake key fixtures MAY be provided to support testing of key rotation, multi-key scenarios, or algorithm variations. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Count fake RSA key constants +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Claude Code MUST NOT skip or defer verification. Automated CI checks MUST verify that build.rs successfully generates C# bindings and that generated files compile. Code review MUST check for proper use of csbindgen configuration and test fixture naming conventions. Static analysis tools MUST scan for usage of test constants in non-test production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-named-authorization-policies-14d3.md b/.actual/rules/cross-cutting-named-authorization-policies-14d3.md new file mode 100644 index 000000000000..e9191747a3c8 --- /dev/null +++ b/.actual/rules/cross-cutting-named-authorization-policies-14d3.md @@ -0,0 +1,42 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Named Authorization Policies + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTHZ-001** SHOULD: Named authorization policies SHOULD correspond to functional boundaries (e.g., 'Scim' for SCIM API endpoints). +- **R-AUTHZ-002** MUST: Production Startup.cs files MUST contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim(). +- **R-AUTHZ-003** MUST: Production configuration files MUST NOT contain authorization policies with RequireAssertion(a => true) or other permissive assertions. +- **R-AUTHZ-004** SHOULD: Test factory classes SHOULD use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs). +- **R-AUTHZ-005** SHOULD: Policy names SHOULD be defined as constants in shared configuration classes and referenced in both policy configuration and controller attributes. +- **R-AUTHZ-006** SHOULD: Authentication schemes SHOULD be configured using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation. +- **R-AUTHZ-007** SHOULD: Authorization policy requirements (scope names, claim types) SHOULD be externalized using IOptions or similar configuration objects rather than hardcoded in Startup. +- **R-AUTHZ-008** SHOULD: Authorization policy requirements SHOULD be documented in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers. +- **R-AUTHZ-009** SHOULD: Logging SHOULD be implemented in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' + +# Verify no permissive assertions in production paths +grep -r 'RequireAssertion.*true' --include='*.cs' | grep -v -E '(Test|Factory|Integration)' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- Policy name strings are defined as constants in shared configuration classes +- Authentication is configured before authorization policies are applied + + +Claude Code MUST NOT skip or defer verification. All rules marked MUST are mandatory; rules marked SHOULD are strongly recommended and deviations require documented justification. Security team review is required for any authorization policy changes before merge to main branch. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-named-http-clients-5dbb.md b/.actual/rules/cross-cutting-named-http-clients-5dbb.md new file mode 100644 index 000000000000..76cba0466a19 --- /dev/null +++ b/.actual/rules/cross-cutting-named-http-clients-5dbb.md @@ -0,0 +1,36 @@ +# Establish HTTP Client Boundaries for External Service Integration: Named Http Clients + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, identity providers, and SSO configuration endpoints. + +### Rules + +- **R-HTTP-001** MUST: Named HTTP clients MUST be used when specific configuration or handler pipelines are required for distinct external service integrations. +- **R-HTTP-002** MUST: All HTTP clients that accept user-supplied URLs MUST include AddSsrfProtection() in their registration pipeline. +- **R-HTTP-003** MUST: All production code MUST use IHttpClientFactory for HTTP client creation with no direct `new HttpClient()` instantiations outside documented legacy exceptions. +- **R-HTTP-004** MUST: Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients. +- **R-HTTP-005** SHOULD: Establish naming conventions and configuration templates for common external service types to prevent configuration drift. +- **R-HTTP-006** SHOULD: Implement startup validation to detect duplicate or misconfigured client registrations. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are present +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct `new HttpClient()` instantiations outside documented legacy exceptions (EXC-001, EXC-002) +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- All AddHttpClient registrations follow naming conventions and configuration templates +- Startup validation detects and prevents duplicate or misconfigured client registrations + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations MUST pass code review checklist verification. Direct HttpClient instantiation patterns MUST be detected via static analysis or custom Roslyn analyzers. Missing SSRF protection on user-facing endpoints MUST trigger security review and block deployment. Violations discovered in production code MUST be tracked as P1 technical debt items with mandatory remediation timeline. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-organization-billing-controller-da79.md b/.actual/rules/cross-cutting-organization-billing-controller-da79.md new file mode 100644 index 000000000000..c455dbacef64 --- /dev/null +++ b/.actual/rules/cross-cutting-organization-billing-controller-da79.md @@ -0,0 +1,35 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Billing Controller + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address operations, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-001** MUST: Organization billing controller actions MUST use [InjectOrganization] attribute to inject the organization entity into the request pipeline. +- **R-BILLING-002** MUST: All organization billing endpoints MUST be decorated with [Authorize] to enforce organization-scoped access control. +- **R-BILLING-003** MUST: All Organization parameters in billing endpoints MUST be marked with [BindNever] to prevent model binding from route parameters or request body. +- **R-BILLING-004** MUST: Organization context MUST only come from [InjectOrganization] and never from route parameters or request body data. +- **R-BILLING-005** SHOULD: Billing-specific authorization requirements SHOULD be placed in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements. +- **R-BILLING-006** SHOULD: Use consistent parameter naming (organization) and binding attributes across all billing endpoints to establish recognizable patterns during code review. + +### Verify + +```bash +# Check for billing controllers missing authorization attributes +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters have [BindNever] protection +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) is consistently applied across all organization billing endpoints + + +Claude Code MUST NOT skip or defer verification. All billing controller endpoints MUST be verified to have the complete three-attribute authorization pattern before accepting changes. Static analysis and code review are mandatory enforcement mechanisms. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-organization-billing-endpoints-1404.md b/.actual/rules/cross-cutting-organization-billing-endpoints-1404.md new file mode 100644 index 000000000000..491741e334ad --- /dev/null +++ b/.actual/rules/cross-cutting-organization-billing-endpoints-1404.md @@ -0,0 +1,34 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Billing Endpoints + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address operations, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-001** MUST: All organization billing endpoints MUST be decorated with `[Authorize]` to enforce organization-scoped billing authorization. +- **R-BILLING-002** MUST: All Organization parameters in billing endpoints MUST be marked with `[BindNever]` attribute to prevent model binding from route parameters or request body. +- **R-BILLING-003** MUST: All Organization entities MUST be injected via `[InjectOrganization]` attribute and never constructed from route parameters or request body data. +- **R-BILLING-004** MUST: The three-attribute pattern (`[Authorize]`, `[InjectOrganization]`, and `[BindNever]`) MUST be applied together on all organization billing endpoints. +- **R-BILLING-005** MUST: Billing-specific authorization requirements MUST be placed in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements. + +### Verify + +```bash +# Verify all billing controllers have authorization attribute +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters have [BindNever] protection +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with `[Authorize]` +- All Organization parameters in billing endpoints are marked with `[BindNever]` and injected via `[InjectOrganization]` +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- The three-attribute pattern is consistently applied across all organization billing endpoints + + +Claude Code MUST NOT skip or defer verification. All billing endpoints must pass automated static analysis checks and code review verification before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-organization-parameters-billing-b978.md b/.actual/rules/cross-cutting-organization-parameters-billing-b978.md new file mode 100644 index 000000000000..c830d4f2234c --- /dev/null +++ b/.actual/rules/cross-cutting-organization-parameters-billing-b978.md @@ -0,0 +1,35 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Parameters Billing + +These rules are ALWAYS ACTIVE for all HTTP endpoints in the Bit.Api.Billing.Controllers namespace that operate on Organization entities, including subscription management, billing address, credit management, payment method operations, and invoice preview endpoints. + +### Rules + +- **R-BILLING-001** MUST: Organization parameters in billing endpoints MUST be marked with [BindNever] to prevent client-supplied organization data from bypassing authorization checks. +- **R-BILLING-002** MUST: All billing controller methods that accept Organization parameters MUST be decorated with [Authorize]. +- **R-BILLING-003** MUST: Organization parameters in billing endpoints MUST be injected via [InjectOrganization] attribute and never constructed from route parameters or request body data. +- **R-BILLING-004** MUST: The three-attribute pattern ([Authorize], [InjectOrganization], and [BindNever]) MUST be applied together on all organization billing endpoints. +- **R-BILLING-005** SHOULD: Billing-specific authorization requirements SHOULD be placed in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements. +- **R-BILLING-006** SHOULD: Consistent parameter naming (organization) and binding attributes ([BindNever]) SHOULD be used across all billing endpoints to establish recognizable patterns during code review. + +### Verify + +```bash +# Check for billing controllers missing authorization attribute +grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' + +# Verify all Organization parameters have [BindNever] protection +grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" + +# Verify all billing endpoints have authorization +find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" +``` + +**Accept when:** +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters +- The three-attribute pattern is consistently applied across all organization billing endpoints + + +Claude Code MUST NOT skip or defer verification. All billing endpoints must pass the verification commands before acceptance. Static analysis and code review must confirm the three-attribute pattern is present on all organization-scoped billing operations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-outbound-http-communication-4af2.md b/.actual/rules/cross-cutting-outbound-http-communication-4af2.md new file mode 100644 index 000000000000..eb468fe8c83d --- /dev/null +++ b/.actual/rules/cross-cutting-outbound-http-communication-4af2.md @@ -0,0 +1,36 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Outbound Http Communication + +These rules are ALWAYS ACTIVE for all outbound HTTP communication to external services across .NET and Rust codebases, including third-party API integrations, distributed system components, and cross-language FFI boundaries requiring HTTP client capabilities. + +### Rules + +- **R-HTTP-001** MUST: All outbound HTTP communication to external services MUST use framework-provided HTTP client abstractions (AddHttpClient in .NET, appropriate client libraries in Rust). +- **R-HTTP-002** MUST: HTTP clients MUST be registered through dependency injection patterns rather than instantiated directly per-request. +- **R-HTTP-003** MUST: Base addresses, default headers, timeout policies, and retry logic MUST be configured at HTTP client registration time, not per-request. +- **R-HTTP-004** MUST: Rust FFI boundaries handling HTTP request/response data MUST use safe string marshaling patterns (std::ffi::{CStr, CString}) with explicit null-termination and UTF-8 validation checks. +- **R-HTTP-005** SHOULD: Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries. +- **R-HTTP-006** SHOULD: For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances. + +### Verify + +```bash +# Count AddHttpClient registrations in .NET services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Detect direct HttpClient instantiation outside tests (should be 0) +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Verify Rust FFI uses safe string marshaling +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients +- No direct HttpClient instantiation patterns detected in production code paths +- Connection pooling and DNS refresh are managed by framework-provided abstractions + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns outside test contexts is mandatory. Code review checklist verification of HTTP client registration is required for all new external service integrations. CI pipeline MUST fail on detection of violations. Architecture review is required for any exception requests, with explicit risk acknowledgment and compensating controls documented. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-production-authorization-policies-0d1f.md b/.actual/rules/cross-cutting-production-authorization-policies-0d1f.md new file mode 100644 index 000000000000..1b8eafdf9ae7 --- /dev/null +++ b/.actual/rules/cross-cutting-production-authorization-policies-0d1f.md @@ -0,0 +1,45 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Production Authorization Policies + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTHZ-001** MUST: Production authorization policies MUST require authenticated users via RequireAuthenticatedUser() +- **R-AUTHZ-002** MUST: Production authorization policies MUST require explicit claim-based authorization using RequireClaim() with JwtClaimTypes.Scope or equivalent scope claims +- **R-AUTHZ-003** MUST: Authentication schemes MUST be configured using AddAuthentication before AddAuthorization to ensure authentication context is available for policy evaluation +- **R-AUTHZ-004** MUST: Policy names MUST be defined as constants in shared configuration classes and referenced in both policy configuration and controller attributes to prevent runtime mismatches +- **R-AUTHZ-005** MUST: Production configuration files MUST NOT contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- **R-AUTHZ-006** SHOULD: Authorization policy requirements (scope names, claim types) SHOULD be externalized using IOptions configuration objects rather than hardcoded in Startup +- **R-AUTHZ-007** SHOULD: Authorization policy requirements SHOULD be documented in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- **R-AUTHZ-008** MAY: Integration test environments MAY use permissive authorization (RequireAssertion(a => true)) in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) to test business logic without authentication infrastructure + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' + +# Verify policy names are defined as constants +grep -r 'const.*string.*[Pp]olicy' --include='*.cs' + +# Confirm test factories use RequireAssertion only in test-specific files +grep -r 'RequireAssertion' --include='*ApplicationFactory.cs' --include='*TestStartup.cs' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- Policy names are defined as constants in shared configuration classes +- Authentication is configured before authorization policies are applied +- Authorization policy requirements are externalized in configuration objects + + +Claude Code MUST NOT skip or defer verification. All R-AUTHZ rules marked MUST are mandatory and must be verified before accepting code changes. Violations in production code paths must trigger CI/CD pipeline failures. Security team review is required for any authorization policy changes before merge to main branch. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-production-authorization-policies-a09e.md b/.actual/rules/cross-cutting-production-authorization-policies-a09e.md new file mode 100644 index 000000000000..5173ba177267 --- /dev/null +++ b/.actual/rules/cross-cutting-production-authorization-policies-a09e.md @@ -0,0 +1,34 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Production Authorization Policies + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints using policy-based authorization configuration. + +### Rules + +- **R-AUTHZ-001** MUST: Production authorization policies MUST call policy.RequireAuthenticatedUser() to enforce authentication as a prerequisite. + +### Verify + +```bash +# Verify services.AddAuthorization configuration exists in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policies require api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers reference authorization policies by name +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration +- No test-specific authorization bypass patterns (RequireAssertion(a => true)) appear in production Startup.cs + + +Claude Code MUST NOT skip or defer verification of authorization policy configuration. All SCIM endpoints MUST be protected by policy-based authorization with authenticated user requirements. Violations block deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-production-code-paths-c368.md b/.actual/rules/cross-cutting-production-code-paths-c368.md new file mode 100644 index 000000000000..9a67c79719a6 --- /dev/null +++ b/.actual/rules/cross-cutting-production-code-paths-c368.md @@ -0,0 +1,36 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Production Code Paths + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-FAKE-RSA-001** MUST NOT: Production code paths MUST NOT reference `_FAKE_RSA_KEY_*` constants; references are permitted only within `#[cfg(test)]` blocks or test-only modules. +- **R-FAKE-RSA-002** MUST: All `_FAKE_RSA_KEY_*` constants MUST be defined in a dedicated test fixtures module (e.g., `rsa_keys.rs`) with `const` visibility and PEM PKCS#8 format. +- **R-FAKE-RSA-003** MUST: Each `_FAKE_RSA_KEY_*` constant MUST include inline documentation explaining its intended test scenario. +- **R-FAKE-RSA-004** SHOULD: CI/CD pipeline SHOULD include automated checks that fail builds if production code references test key constants. +- **R-FAKE-RSA-005** SHOULD: Pre-commit hooks SHOULD grep for `_FAKE_RSA_KEY_` references outside test contexts and reject commits that violate this rule. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key test suite passes +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- All 5 fake RSA keys (0-4) are present and valid +- Pre-commit hooks and CI verification scripts are configured and operational + + +Claude Code MUST NOT skip or defer verification of these rules. All `_FAKE_RSA_KEY_*` references must be confined to test contexts. Violations block builds and require immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-production-scim-policies-3121.md b/.actual/rules/cross-cutting-production-scim-policies-3121.md new file mode 100644 index 000000000000..1a43692e7e5b --- /dev/null +++ b/.actual/rules/cross-cutting-production-scim-policies-3121.md @@ -0,0 +1,36 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Production Scim Policies + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including all SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes, services implementing IScimContext and ICurrentContext interfaces, controllers decorated with authorization policy attributes, and middleware pipeline components between UseAuthentication and UseAuthorization. + +### Rules + +- **R-SCIM-001** MUST: Production SCIM policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim'). +- **R-SCIM-002** MUST: Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation. +- **R-SCIM-003** MUST: Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation. +- **R-SCIM-004** MUST: Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity. +- **R-SCIM-005** MUST: All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy. +- **R-SCIM-006** MUST: Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope. +- **R-SCIM-007** MUST: Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods. + +### Verify + +```bash +# Verify AddAuthorization configuration with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify RequireClaim for api.scim scope +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- No SCIM endpoints lack policy enforcement point coverage + + +Claude Code MUST NOT skip or defer verification of these rules. Authorization policy configuration violations MUST be caught during code review and integration testing. Pull requests missing authorization policy configuration for new SCIM endpoints MUST be blocked. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-protected-controller-actions-2188.md b/.actual/rules/cross-cutting-protected-controller-actions-2188.md new file mode 100644 index 000000000000..f25586bf475a --- /dev/null +++ b/.actual/rules/cross-cutting-protected-controller-actions-2188.md @@ -0,0 +1,32 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Protected Controller Actions + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with protected actions, organization user management operations, SCIM integration endpoints, administrative console controllers, and bulk operations affecting protected resources. + +### Rules + +- **R-AUTHZ-001** MUST: All protected API controller actions MUST use `IAuthorizationService.AuthorizeAsync()` to enforce authorization decisions before performing operations on protected resources. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one `IAuthorizationService.AuthorizeAsync()` call before performing operations on protected resources +- Authorization policies are configured using `services.AddAuthorization()` and custom requirements implement `IAuthorizationRequirement` +- Authorization failures result in appropriate HTTP error responses (`NotFoundException`, `UnauthorizedAccessException`, or `BadRequestException` with error messages) +- `IAuthorizationService` is injected as a private readonly field in controller constructors +- Custom authorization requirements implement `IAuthorizationRequirement` interface with corresponding `AuthorizationHandler` or `AuthorizationHandler` classes +- Bulk operations iterate through resources and verify authorization for each resource instance + + +Claude Code MUST NOT skip or defer verification. Static code analysis tools MUST scan for controller actions with `[Authorize]` attributes missing corresponding `AuthorizeAsync` calls. Integration tests MUST verify authorization enforcement for each protected endpoint with unauthorized users. Security-focused code reviews MUST check authorization logic in new and modified controller actions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-protected-controller-actions-358e.md b/.actual/rules/cross-cutting-protected-controller-actions-358e.md new file mode 100644 index 000000000000..cb0f71e5ce96 --- /dev/null +++ b/.actual/rules/cross-cutting-protected-controller-actions-358e.md @@ -0,0 +1,36 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Protected Controller Actions + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations requiring authorization enforcement across the Api and AdminConsole projects. + +### Rules + +- **R-AUTH-001** MUST: All protected API controller actions MUST use the [Authorize] attribute with a generic type parameter specifying a custom requirement class that implements IAuthorizationRequirement. +- **R-AUTH-002** MUST: Custom requirement classes MUST be defined in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced. +- **R-AUTH-003** MUST: Authorization failures MUST throw NotFoundException rather than UnauthorizedAccessException to prevent information disclosure about resource existence. +- **R-AUTH-004** SHOULD: Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership). +- **R-AUTH-005** SHOULD: Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it. +- **R-AUTH-006** MAY: Public endpoints explicitly marked with [AllowAnonymous] are exempt from this requirement and MUST include justification in code comments. + +### Verify + +```bash +# Count [Authorize<*Requirement>] attributes in Api controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find unprotected controller actions accessing protected resources +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- All [AllowAnonymous] usage is documented with justification in code comments + + +Claude Code MUST NOT skip or defer verification of these rules. Static analysis failures blocking pull request merging until authorization attributes are added, code review checklist verification, and security team review of new custom requirement classes are mandatory. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-protected-controller-endpoints-77bc.md b/.actual/rules/cross-cutting-protected-controller-endpoints-77bc.md new file mode 100644 index 000000000000..c238fd1e4013 --- /dev/null +++ b/.actual/rules/cross-cutting-protected-controller-endpoints-77bc.md @@ -0,0 +1,35 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Protected Controller Endpoints + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, and service configuration registering authorization policies. + +### Rules + +- **R-AUTH-001** MUST: All protected controller endpoints MUST use IAuthorizationService to evaluate authorization requirements before granting access to resources. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization is registered +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count authorization handler implementations +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- Authorization failures throw NotFoundException to prevent information disclosure +- Public endpoints are explicitly marked with [AllowAnonymous] attribute + + +Claude Code MUST NOT skip or defer verification. All protected controller endpoints MUST be verified to use IAuthorizationService before granting access to resources. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-endpoints-that-05a5.md b/.actual/rules/cross-cutting-public-endpoints-that-05a5.md new file mode 100644 index 000000000000..a8cf98c32ab4 --- /dev/null +++ b/.actual/rules/cross-cutting-public-endpoints-that-05a5.md @@ -0,0 +1,35 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Public Endpoints That + +These rules are ALWAYS ACTIVE for all internal API endpoint implementations in the AdminConsole and Admin controllers requiring authorization enforcement. + +### Rules + +- **R-AUTH-001** MAY: Public endpoints that do not require authentication MAY omit authorization attributes, but MUST be explicitly documented as public access points. +- **R-AUTH-002** MUST: All internal API controller actions managing organization resources have authorization attributes applied. +- **R-AUTH-003** MUST: Authorization attributes be applied at the action level rather than the controller class level to enable fine-grained authorization control. +- **R-AUTH-004** MUST: Public endpoints omitting authorization attributes include [AllowAnonymous] attribute with accompanying security rationale in code comments. +- **R-AUTH-005** MUST: Custom authorization requirement classes implement IAuthorizationRequirement interface and corresponding authorization handlers inherit from AuthorizationHandler. +- **R-AUTH-006** MUST: Authorization handlers be registered in the dependency injection container during application startup. + +### Verify + +```bash +# Verify authorization attribute coverage on internal API endpoints +grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l + +# Verify public action methods have authorization attributes or AllowAnonymous +grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" + +# Run authorization-specific unit tests +dotnet test --filter "Category=Authorization" --no-build --verbosity normal +``` + +**Accept when:** +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes +- All public endpoints are explicitly marked with [AllowAnonymous] and include security rationale documentation + + +Claude Code MUST NOT skip or defer verification. All rules must be verified before accepting changes to authorization-protected endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-endpoints-that-46c1.md b/.actual/rules/cross-cutting-public-endpoints-that-46c1.md new file mode 100644 index 000000000000..e3024da39407 --- /dev/null +++ b/.actual/rules/cross-cutting-public-endpoints-that-46c1.md @@ -0,0 +1,37 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Public Endpoints That + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and Minimal API controllers in Api and Admin projects, specifically for HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources. + +### Rules + +- **R-AUTH-001** MUST: Public endpoints that bypass authorization MUST explicitly declare `[AllowAnonymous]` to document the intentional security exception. +- **R-AUTH-002** MUST: All controller action methods returning `IResult` or `IActionResult` MUST have either `[Authorize]`, `[Authorize]`, or `[AllowAnonymous]` attributes. +- **R-AUTH-003** MUST: Custom authorization requirement classes MUST implement `IAuthorizationRequirement` and have corresponding registered handler implementations. +- **R-AUTH-004** SHOULD: Create custom authorization requirements by implementing `IAuthorizationRequirement` marker interface and corresponding `AuthorizationHandler` or `AuthorizationHandler` implementations. +- **R-AUTH-005** SHOULD: Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs). +- **R-AUTH-006** SHOULD: For actions requiring multiple authorization checks, apply multiple `[Authorize]` attributes or create composite requirement types that evaluate multiple conditions. +- **R-AUTH-007** SHOULD: Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes. + +### Verify + +```bash +# Detect controller actions without authorization attributes +grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Verify all custom requirement classes implement IAuthorizationRequirement +find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" + +# Run authorization-focused tests +dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All controller action methods returning `IResult` or `IActionResult` have either `[Authorize]`, `[Authorize]`, or `[AllowAnonymous]` attributes. +- All custom requirement classes implement `IAuthorizationRequirement` and have corresponding registered handler implementations. +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases. +- Static analysis passes with no violations of authorization attribute requirements on public controller actions. +- All `[AllowAnonymous]` usage is documented with security rationale in code comments and approved by security team. + + +Claude Code MUST NOT skip or defer verification of authorization attributes on controller actions. All public endpoints MUST be explicitly marked with authorization or `[AllowAnonymous]` attributes. Security review approval is mandatory for any `[AllowAnonymous]` usage. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-endpoints-that-dff2.md b/.actual/rules/cross-cutting-public-endpoints-that-dff2.md new file mode 100644 index 000000000000..dac1e235595c --- /dev/null +++ b/.actual/rules/cross-cutting-public-endpoints-that-dff2.md @@ -0,0 +1,40 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Public Endpoints That + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controller implementations in the Api and AdminConsole projects that require authorization enforcement. + +### Rules + +- **R-AUTH-001** SHOULD: Public endpoints that do not require authentication SHOULD be explicitly marked with [AllowAnonymous] to document the intentional absence of authorization. +- **R-AUTH-002** MUST: All protected controller actions accessing organizational or user resources MUST include [Authorize] attributes with custom requirement classes. +- **R-AUTH-003** MUST: Custom requirement classes MUST be defined in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with consistent naming conventions. +- **R-AUTH-004** MUST: Authorization failures MUST throw NotFoundException rather than UnauthorizedAccessException to prevent information disclosure about resource existence. +- **R-AUTH-005** SHOULD: ICurrentContext SHOULD be used for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership). +- **R-AUTH-006** MUST: All new custom requirement classes MUST be reviewed by the security team to ensure consistent authorization semantics. + +### Verify + +```bash +# Count existing [Authorize] attributes +grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l + +# Find controller actions without authorization attributes +grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" + +# Find controllers missing authorization namespace imports +find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +# Verify [AllowAnonymous] usage is documented +grep -r "\[AllowAnonymous\]" src/Api --include="*.cs" -B 2 | grep -E "//|///" +``` + +**Accept when:** +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions (e.g., *Requirement suffix) +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate +- All [AllowAnonymous] endpoints include code comments justifying the intentional absence of authorization +- No unprotected endpoints exist that access organizational or user-specific resources + + +Claude Code MUST NOT skip or defer verification. Static analysis failures block pull request merging until authorization attributes are added. Code review process requires explicit justification for any [AllowAnonymous] usage. Security team review is required for any new custom requirement classes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-ffi-functions-4d31.md b/.actual/rules/cross-cutting-public-ffi-functions-4d31.md new file mode 100644 index 000000000000..1bd190e433b0 --- /dev/null +++ b/.actual/rules/cross-cutting-public-ffi-functions-4d31.md @@ -0,0 +1,36 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Public Ffi Functions + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs that expose cryptographic key generation and management functions to C consumers, including all string parameters and return values crossing the Rust/C FFI boundary. + +### Rules + +- **R-FFI-001** MUST: Public FFI functions that return heap-allocated strings MUST transfer ownership to the C caller using c_char pointers via CString::into_raw(). +- **R-FFI-002** MUST: All public FFI functions returning strings MUST document the requirement to call free_c_string for deallocation in their documentation. +- **R-FFI-003** MUST: A free_c_string function MUST be exported in the public API to enable C callers to safely deallocate Rust-allocated strings using CString::from_raw(). +- **R-FFI-004** MUST: Input validation MUST check for null pointers using .is_null() before dereferencing c_char pointers received from C. +- **R-FFI-005** SHOULD: Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns. +- **R-FFI-006** MAY: Static string literals that do not require deallocation are excepted from ownership transfer requirements (EXC-001). + +### Verify + +```bash +# Count CString::into_raw and CString::from_raw usage +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists and is exported +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use CString::into_raw() and document the free_c_string requirement in their documentation +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters in all public FFI functions +- Documentation includes examples of correct string ownership transfer and deallocation patterns +- Static string literal exceptions are documented with EXC-001 reference in code comments + + +Clause Code MUST NOT skip or defer verification of FFI string handling patterns. Memory safety violations in cryptographic key material handling across FFI boundaries require immediate remediation. All public FFI functions must be audited for compliance with R-FFI-001 through R-FFI-004 before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-ffi-functions-d7cf.md b/.actual/rules/cross-cutting-public-ffi-functions-d7cf.md new file mode 100644 index 000000000000..5fab29ab9e53 --- /dev/null +++ b/.actual/rules/cross-cutting-public-ffi-functions-d7cf.md @@ -0,0 +1,34 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Public Ffi Functions + +These rules are ALWAYS ACTIVE for all public FFI functions in the Rust SDK that accept c_char pointers or handle cryptographic material across C interop boundaries. + +### Rules + +- **R-FFI-001** SHOULD: Public FFI functions (pub extern "C") SHOULD document their null-safety requirements and expected string encoding in comments. +- **R-FFI-002** MUST: All public FFI functions accepting c_char pointers MUST use CStr::from_ptr() for validation before use. +- **R-FFI-003** MUST: All FFI functions returning strings MUST use CString and provide corresponding free functions. +- **R-FFI-004** MUST: FFI functions handling cryptographic material MUST validate all external input before processing. +- **R-FFI-005** SHOULD: Unit tests SHOULD cover null pointer, invalid UTF-8, and missing terminator cases for FFI functions. + +### Verify + +```bash +# Count FFI functions using CStr/CString patterns +grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l + +# Verify public FFI functions use CStr::from_ptr or CString::new +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' + +# Check FFI test coverage for validation scenarios +cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' +``` + +**Accept when:** +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions +- Documentation comments on public FFI functions describe null-safety requirements and expected string encoding + + +Claude Code MUST NOT skip or defer verification. All public FFI functions handling c_char pointers or cryptographic material MUST be reviewed against these rules before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-public-ffi-functions-fbef.md b/.actual/rules/cross-cutting-public-ffi-functions-fbef.md new file mode 100644 index 000000000000..b98a0812225c --- /dev/null +++ b/.actual/rules/cross-cutting-public-ffi-functions-fbef.md @@ -0,0 +1,36 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Public Ffi Functions + +These rules are ALWAYS ACTIVE for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers, specifically all public extern "C" functions in util/RustSdk/rust/src/lib.rs and FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs. + +### Rules + +- **R-FFI-001** MUST: All public FFI functions accepting c_char pointers MUST convert them to CStr using CStr::from_ptr before accessing the underlying data. +- **R-FFI-002** MUST: Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers. +- **R-FFI-003** MUST: Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-004** MUST: For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks. +- **R-FFI-005** SHOULD: Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior. +- **R-FFI-006** SHOULD: Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files. + +### Verify + +```bash +# Verify all extern "C" functions accepting c_char pointers use CStr::from_ptr +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify count of CString::into_raw matches string-returning FFI functions +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi +``` + +**Accept when:** +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling +- Grep verification commands return empty results (indicating all FFI functions use CStr) +- Cargo test suite passes all FFI-specific tests + + +Claude Code MUST NOT skip or defer verification. All public extern "C" functions accepting c_char pointers MUST be validated against R-FFI-001 through R-FFI-004 before approval. Violations result in CI build failure and code review rejection. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-push-notification-services-09af.md b/.actual/rules/cross-cutting-push-notification-services-09af.md new file mode 100644 index 000000000000..b66a15113cb6 --- /dev/null +++ b/.actual/rules/cross-cutting-push-notification-services-09af.md @@ -0,0 +1,30 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Push Notification Services + +These rules are ALWAYS ACTIVE for all implementations of IPushNotificationService interface, push notification processing logic handling Bit.Core.NotificationCenter.Entities, validation logic for notification IDs and status IDs, and runtime quality gates for notification state verification. + +### Rules + +- **R-PUSH-001** MUST: Push notification services MUST log warning-level events when encountering invalid notification IDs using structured logging with the notification ID as a parameter. + +### Verify + +```bash +# Verify warning-level logging for invalid notification IDs +grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' + +# Verify IPushNotificationService implementations include logger.LogWarning +grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' + +# Verify pragma warning disable directives are present and documented +find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; +``` + +**Accept when:** +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate +- Structured logging templates follow the pattern: `logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id)` + + +Claude Code MUST NOT skip or defer verification. All push notification service implementations MUST include warning-level structured logging for invalid notification states before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-push-notification-services-2769.md b/.actual/rules/cross-cutting-push-notification-services-2769.md new file mode 100644 index 000000000000..18a2461a57cf --- /dev/null +++ b/.actual/rules/cross-cutting-push-notification-services-2769.md @@ -0,0 +1,30 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Push Notification Services + +These rules are ALWAYS ACTIVE for all implementations of IPushNotificationService interface, push notification processing logic handling Bit.Core.NotificationCenter.Entities, validation logic for notification IDs and status IDs, and runtime quality gates for notification state verification. + +### Rules + +- **R-PUSH-001** MUST: Push notification services MUST log warning-level events when encountering invalid notification status IDs using structured logging with the notification ID as a parameter. + +### Verify + +```bash +# Verify warning-level logging for invalid notification IDs +grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' + +# Verify LogWarning usage in IPushNotificationService implementations +grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' + +# Identify pragma warning disable directives in push notification services +find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; +``` + +**Accept when:** +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate +- Structured logging templates follow the pattern: `logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id)` + + +Claude Code MUST NOT skip or defer verification. All push notification service implementations MUST include warning-level structured logging for invalid notification states before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-read-only-collection-e4b3.md b/.actual/rules/cross-cutting-read-only-collection-e4b3.md new file mode 100644 index 000000000000..63d10f23660a --- /dev/null +++ b/.actual/rules/cross-cutting-read-only-collection-e4b3.md @@ -0,0 +1,36 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Read Only Collection + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, and for operations modifying user access to collections or groups within multi-tenant organizations. + +### Rules + +- **R-AUTHZ-001** MUST: Perform authorization checks using IAuthorizationService with typed requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) before domain validation logic in all organization user management endpoints. +- **R-AUTHZ-002** MUST: Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization checks fail to prevent information disclosure about resource existence in multi-tenant environments. +- **R-AUTHZ-003** MUST: Load all affected collections and verify BulkCollectionOperations.ModifyUserAccess authorization before applying changes to user collection access. +- **R-AUTHZ-004** SHOULD: Preserve read-only collection access during user updates by combining editable collections with readonly collections the updating user cannot modify. +- **R-AUTHZ-005** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-AUTHZ-006** MUST: Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges. + +### Verify + +```bash +# Count authorization checks using BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Verify NotFoundException is thrown after authorization checks +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- Read-only collections are preserved during user updates by filtering collections the updating user cannot modify and combining them with editable collections + + +Claude Code MUST NOT skip or defer verification. All rules must be verified through code review, static analysis, and integration testing before accepting changes to organization user management endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-redis-connection-failures-4ea5.md b/.actual/rules/cross-cutting-redis-connection-failures-4ea5.md new file mode 100644 index 000000000000..83699dbbf351 --- /dev/null +++ b/.actual/rules/cross-cutting-redis-connection-failures-4ea5.md @@ -0,0 +1,29 @@ +# Expose Extended Cache Configuration as Public API Contract: Redis Connection Failures + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in the Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-REDIS-001** MUST: Redis connection failures during cache initialization MUST be logged via ILogger.LogError with cache name context. + +### Verify + +```bash +# Verify AddExtendedCache usage across the codebase +grep -r 'AddExtendedCache' --include='*.cs' / + +# Identify direct AddStackExchangeRedisCache calls outside the extension +grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify Redis connection error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + + +Claude Code MUST NOT skip or defer verification. Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods MUST be enforced. CI pipeline MUST fail if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-redis-connection-failures-6ee5.md b/.actual/rules/cross-cutting-redis-connection-failures-6ee5.md new file mode 100644 index 000000000000..9cdb41d1b163 --- /dev/null +++ b/.actual/rules/cross-cutting-redis-connection-failures-6ee5.md @@ -0,0 +1,33 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Redis Connection Failures + +These rules are ALWAYS ACTIVE for all distributed caching implementations using Redis through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions in Bit.Core and dependent services. + +### Rules + +- **R-REDIS-001** MUST: Redis connection failures MUST be logged with structured logging including cache name context using ILogger.LogError + +### Verify + +```bash +# Verify all distributed cache usage employs IDistributedCache interface +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Check for IDistributedCache usage patterns +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration is used +grep -r 'AddExtendedCache' --include='*.cs' + +# Detect direct Redis client usage outside infrastructure layer +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + + +Clause Code MUST NOT skip or defer verification of R-REDIS-001 compliance. All pull requests introducing distributed caching must demonstrate structured error logging with cache name context for Redis connection failures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-redis-connection-failures-7cfd.md b/.actual/rules/cross-cutting-redis-connection-failures-7cfd.md new file mode 100644 index 000000000000..c77c920430dc --- /dev/null +++ b/.actual/rules/cross-cutting-redis-connection-failures-7cfd.md @@ -0,0 +1,30 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Redis Connection Failures + +These rules are ALWAYS ACTIVE for all cache service registration extensions and distributed cache initialization code that uses StackExchangeRedis and Microsoft.Extensions.Caching.StackExchangeRedis. + +### Rules + +- **R-REDIS-001** MUST: Redis connection failures during cache initialization MUST be logged using ILogger.LogError with the exception object and cache name context. + +### Verify + +```bash +# Verify Redis connection error logging is present +grep -r 'LogError.*Failed to connect to Redis' src/ + +# Verify ConnectionMultiplexer.Connect calls are wrapped with try-catch +grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' + +# Run cache initialization tests with detailed logging +dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" +``` + +**Accept when:** +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters +- Connection strings are sanitized and do not leak credentials in log output + + +Claude Code MUST NOT skip or defer verification. All Redis connection initialization code MUST include error logging per R-REDIS-001. Code review and static analysis must confirm compliance before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-redis-connection-failures-ffdd.md b/.actual/rules/cross-cutting-redis-connection-failures-ffdd.md new file mode 100644 index 000000000000..7d46305e0d34 --- /dev/null +++ b/.actual/rules/cross-cutting-redis-connection-failures-ffdd.md @@ -0,0 +1,30 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Redis Connection Failures + +These rules are ALWAYS ACTIVE for all distributed cache implementations within the Bit.Core namespace, service registration code in ExtendedCacheServiceCollectionExtensions, Redis connection management and error handling for cache instances, and cache configuration sourced from Bit.Core.Settings. + +### Rules + +- **R-REDIS-001** MUST: Redis connection failures during cache initialization MUST be logged with LogError including the cache name and exception details. + +### Verify + +```bash +# Verify StackExchange.Redis package is present in Core project dependencies +grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . + +# Verify all distributed cache registrations use AddExtendedCache +grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' + +# Verify ConnectionMultiplexer usage patterns +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . +``` + +**Accept when:** +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details +- No direct RedisCacheOptions configuration exists outside approved extension methods + + +Clause R-REDIS-001 MUST be verified before any code touching distributed cache registration or Redis connection handling is merged. Violations require architectural review and explicit exception documentation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-redis-connections-established-6e7b.md b/.actual/rules/cross-cutting-redis-connections-established-6e7b.md new file mode 100644 index 000000000000..83fbd7c87bdf --- /dev/null +++ b/.actual/rules/cross-cutting-redis-connections-established-6e7b.md @@ -0,0 +1,41 @@ +# Use Redis via StackExchange.Redis for Distributed Caching with Extended Cache Utilities: Redis Connections Established + +These rules are ALWAYS ACTIVE for all distributed caching implementations in Bit.Core and dependent services that require Redis-backed cache instances registered through dependency injection. + +### Rules + +- **R-REDIS-001** MUST: Redis connections MUST be established through StackExchange.Redis ConnectionMultiplexer.Connect with connection string configuration. +- **R-REDIS-002** MUST: All distributed cache usage in the codebase MUST use the IDistributedCache interface rather than direct Redis client references. +- **R-REDIS-003** MUST: Service collection registration for distributed cache MUST be performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities namespace. +- **R-REDIS-004** MUST: Redis connection failures MUST be logged with structured logging including cache name context. +- **R-REDIS-005** MUST: No direct StackExchange.Redis client usage is permitted outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer. + +### Verify + +```bash +# Verify IDistributedCache usage without direct Redis client references +grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify IDistributedCache interface adoption +grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 + +# Verify AddExtendedCache registration pattern +grep -r 'AddExtendedCache' --include='*.cs' + +# Verify ConnectionMultiplexer.Connect usage is isolated +grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +# Verify no direct StackExchange.Redis usage outside infrastructure +grep -r 'StackExchange.Redis' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' | grep -v 'using' +``` + +**Accept when:** +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchange.Redis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer +- Connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments + + +Claude Code MUST NOT skip or defer verification of these rules. Code review checklist verification of IDistributedCache usage and proper service collection registration is mandatory. Static analysis rules detecting direct Redis client usage outside infrastructure layer must be applied. Integration tests validating cache behavior with both Redis and in-memory implementations are required. Pull requests introducing direct Redis client usage outside infrastructure layer MUST be blocked pending refactoring. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-restful-http-verbs-5544.md b/.actual/rules/cross-cutting-restful-http-verbs-5544.md new file mode 100644 index 000000000000..467ae0aa5b7e --- /dev/null +++ b/.actual/rules/cross-cutting-restful-http-verbs-5544.md @@ -0,0 +1,34 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Restful Http Verbs + +These rules are ALWAYS ACTIVE for all ASP.NET Core controller classes and service API boundaries that expose HTTP endpoints. + +### Rules + +- **R-CQRS-001** MUST: RESTful HTTP verbs (POST, DELETE, GET, PUT, PATCH) MUST align with command-query semantics, with commands using POST/PUT/PATCH/DELETE and queries using GET. +- **R-CQRS-002** MUST: All API controller action methods MUST use async Task signatures and await command/query interface methods rather than performing direct data access. +- **R-CQRS-003** MUST: Controllers MUST inject command/query interfaces (e.g., ISceneExecutor, IDestroySceneCommand, IQueries) via constructor dependency injection instead of directly accessing DbContext or persistence layers. +- **R-CQRS-004** MUST: All data access operations MUST use Task-based async/await patterns (ExecuteAsync, DestroyAsync, query methods) at service boundaries. +- **R-CQRS-005** SHOULD: Error handling SHOULD distinguish between aggregate failures (batch operations) and single execution failures, providing structured error responses at the API boundary. +- **R-CQRS-006** SHOULD: Structured logging SHOULD be added at API boundary entry points using ILogger with semantic context (PlayIds, Template parameters) for operation traceability. + +### Verify + +```bash +# Verify all controller action methods use async Task pattern +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access in controllers (DbContext, SaveChanges, Query, Execute) +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files with async/await patterns +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access. +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments). +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar). + + +Clause Code MUST NOT skip or defer verification. All violations MUST be resolved before merge, or explicitly exempted with architectural review and [ADR-AUTO-EXCEPTION] documentation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-result-types-expose-4249.md b/.actual/rules/cross-cutting-result-types-expose-4249.md new file mode 100644 index 000000000000..ca2ce75a0023 --- /dev/null +++ b/.actual/rules/cross-cutting-result-types-expose-4249.md @@ -0,0 +1,31 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Result Types Expose + +These rules are ALWAYS ACTIVE for all ASP.NET Core endpoint handlers, custom HTTP result types, and integration test implementations within the configured scope. + +### Rules + +- **R-IRESULT-001** MAY: Result types MAY expose strongly-typed Value properties through IValueHttpResult for type-safe response inspection. + +### Verify + +```bash +# Verify IResult interface implementation in result types +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns (excluding direct Response.WriteAsync) +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration tests use Server HTTP methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result types are sealed classes with internal constructors and readonly fields for wrapped instances +- Factory methods or extension methods are used for creating custom results rather than public constructors + + +Claude Code MUST NOT skip or defer verification of IResult interface implementation, ExecuteAsync delegation patterns, and integration test method usage. All violations MUST be flagged during code review and architecture assessment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-result-types-implement-459e.md b/.actual/rules/cross-cutting-result-types-implement-459e.md new file mode 100644 index 000000000000..a70cc9857a2a --- /dev/null +++ b/.actual/rules/cross-cutting-result-types-implement-459e.md @@ -0,0 +1,36 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Result Types Implement + +These rules are ALWAYS ACTIVE for all ASP.NET Core endpoint handlers, custom HTTP result types, and integration test implementations within the configured scope. + +### Rules + +- **R-IRESULT-001** SHOULD: Result types SHOULD implement marker interfaces (IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) to expose metadata without executing the result. +- **R-IRESULT-002** MUST: Custom result types MUST implement IResult and delegate ExecuteAsync to inner framework results. +- **R-IRESULT-003** MUST: Endpoint handlers MUST NOT perform direct HttpContext.Response manipulation outside approved middleware exceptions. +- **R-IRESULT-004** SHOULD: Integration tests SHOULD use Server.GetAsync/PostAsync/PutAsync/PatchAsync methods rather than constructing HttpContext instances directly. +- **R-IRESULT-005** SHOULD: Custom result types SHOULD be implemented as sealed classes wrapping framework results with internal constructors to control instantiation. +- **R-IRESULT-006** SHOULD: Result wrapper hierarchies SHOULD be limited to single-level delegation to avoid excessive performance overhead. + +### Verify + +```bash +# Verify IResult interface implementation in result types +grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ + +# Verify ExecuteAsync delegation patterns +grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' + +# Verify integration test patterns use Server methods +grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ +``` + +**Accept when:** +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions (EXC-001) +- Custom result types are sealed classes with internal constructors and readonly field storage +- Result wrapper depth does not exceed single-level delegation + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for code review and CI pipeline validation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-return-fallback-responses-ecab.md b/.actual/rules/cross-cutting-return-fallback-responses-ecab.md new file mode 100644 index 000000000000..43a6d93edad3 --- /dev/null +++ b/.actual/rules/cross-cutting-return-fallback-responses-ecab.md @@ -0,0 +1,41 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Return Fallback Responses + +These rules are ALWAYS ACTIVE for controller methods decorated with [Authorize] or custom authorization requirements, operations involving external HTTP clients (IHttpClientFactory usage), third-party service integrations (Stripe, external APIs), and multi-step operations where partial success is acceptable. + +### Rules + +- **R-FALLBACK-001** MAY: Return fallback responses (e.g., '-' or error JSON) to clients when external service calls fail, with appropriate HTTP status codes for true errors. +- **R-FALLBACK-002** MUST: Inject ILogger via constructor dependency injection in all controller classes that call external services. +- **R-FALLBACK-003** MUST: Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical to the primary request. +- **R-FALLBACK-004** MUST: Use ILogger.LogError with exception object and at least one structured parameter (named placeholder) for all external service failures. +- **R-FALLBACK-005** MUST: Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)). +- **R-FALLBACK-006** SHOULD: Include context about primary operation state in log messages (e.g., 'Database updated successfully') to help correlate partial success scenarios. +- **R-FALLBACK-007** MUST NOT: Log sensitive data (tokens, API keys) in exception messages or structured parameters. +- **R-FALLBACK-008** MUST NOT: Use string concatenation for log messages; use structured logging with named placeholders instead. + +### Verify + +```bash +# Find all LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find all catch blocks with LogError in API and Admin namespaces +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-specific tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +# Verify no string concatenation in LogError calls +grep -r 'LogError.*+' --include='*.cs' src/ | grep -v '//' +``` + +**Accept when:** +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern +- No sensitive data (tokens, API keys) appears in logged exception messages or parameters +- All LogError calls use named placeholders instead of string concatenation + + +Clause Code MUST NOT skip or defer verification. All rules in this file are mandatory for pull requests modifying controller methods that integrate with external services. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-rsa-key-operations-065c.md b/.actual/rules/cross-cutting-rsa-key-operations-065c.md new file mode 100644 index 000000000000..80d18873a737 --- /dev/null +++ b/.actual/rules/cross-cutting-rsa-key-operations-065c.md @@ -0,0 +1,39 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Rsa Key Operations + +These rules are ALWAYS ACTIVE for all cryptographic key generation functions exposed through C FFI boundaries in the Rust SDK, including generate_user_keys, generate_organization_keys, generate_user_organization_key, and related memory management functions. + +### Rules + +- **R-RSA-001** MUST: RSA key operations MUST use a managed pool (RSA_POOL) to coordinate resource lifecycle. +- **R-RSA-002** MUST: All public FFI functions that allocate memory MUST provide a corresponding free_* function and document the caller's responsibility to invoke it. +- **R-RSA-003** MUST: Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead. +- **R-RSA-004** MUST: Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths. +- **R-RSA-005** MUST: All FFI boundary functions for key generation MUST use c_char pointers with CString/CStr conversions from std::ffi. +- **R-RSA-006** SHOULD: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks to prevent mock divergence from production behavior. +- **R-RSA-007** SHOULD: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns. + +### Verify + +```bash +# Verify FFI functions use c_char pointers with CString/CStr conversions +grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' + +# Verify free_c_string function exists in public API +grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs + +# Verify std::ffi types are imported and used +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations +- RSA_POOL is used to manage RSA key resource lifecycle +- Input validation is performed at FFI boundaries before passing to cryptographic functions +- CString conversions are wrapped with panic handling to prevent FFI boundary violations +- Test infrastructure includes both unit tests with mocks and integration tests with real cryptographic implementations + + +Claude Code MUST NOT skip or defer verification. Code review of all FFI boundary functions must verify paired allocation/deallocation. Static analysis must detect CString conversions without corresponding error handling. Memory leak detection in CI using valgrind or similar tools must pass on FFI integration tests. FFI functions without paired deallocation functions must be rejected in code review. Memory leaks detected in CI must block merge until resolved. Panics at FFI boundaries must be converted to error returns before production deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-rust-sdk-modules-4738.md b/.actual/rules/cross-cutting-rust-sdk-modules-4738.md new file mode 100644 index 000000000000..51d4d3523f0b --- /dev/null +++ b/.actual/rules/cross-cutting-rust-sdk-modules-4738.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Rust Sdk Modules + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts and test fixtures used for cryptographic operation testing. + +### Rules + +- **R-CSHARP-FFI-001** MUST: All Rust SDK modules exposing public APIs to C# MUST use csbindgen to generate C# binding code during the build process. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Verify test fixture naming conventions are in place +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated C# bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Claude Code MUST NOT skip or defer verification. Automated CI checks MUST verify that build.rs successfully generates C# bindings and that generated files compile. Code review MUST check for proper use of csbindgen configuration and test fixture naming conventions. Static analysis tools MUST scan for usage of test constants in non-test production code paths. Violations result in CI build failures, code review rejection, or security review escalation as appropriate. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scim-endpoint-authorization-f6bd.md b/.actual/rules/cross-cutting-scim-endpoint-authorization-f6bd.md new file mode 100644 index 000000000000..4c73161f5161 --- /dev/null +++ b/.actual/rules/cross-cutting-scim-endpoint-authorization-f6bd.md @@ -0,0 +1,33 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Scim Endpoint Authorization + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing SCIM endpoints and authorization policies. + +### Rules + +- **R-SCIM-001** MUST: SCIM endpoint authorization policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, "api.scim") + +### Verify + +```bash +# Verify AddAuthorization configuration exists in Startup.cs +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify api.scim scope claim requirement is configured +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify Authorize attributes reference the Scim policy +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + + +Clause Code MUST NOT skip or defer verification of SCIM endpoint authorization policy configuration. All SCIM endpoints MUST be protected by policy-based authorization requiring the 'api.scim' scope claim. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scim-endpoint-tests-3944.md b/.actual/rules/cross-cutting-scim-endpoint-tests-3944.md new file mode 100644 index 000000000000..9926f2059741 --- /dev/null +++ b/.actual/rules/cross-cutting-scim-endpoint-tests-3944.md @@ -0,0 +1,35 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Scim Endpoint Tests + +These rules are ALWAYS ACTIVE for all SCIM integration tests in `bitwarden_license/test/Scim.IntegrationTest/` and related test infrastructure including ScimApplicationFactory and DatabaseContext operations. + +### Rules + +- **R-SCIM-001** MUST: SCIM endpoint tests MUST use async HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) with await for coordinated database access. +- **R-SCIM-002** MUST: Call DatabaseContext.SaveChanges() or SaveChangesAsync() after all test entities are created but before executing HTTP requests. +- **R-SCIM-003** MUST: Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order. +- **R-SCIM-004** MUST: Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data. +- **R-SCIM-005** SHOULD: Batch related entity creation and call SaveChanges once per logical setup phase to avoid performance degradation. +- **R-SCIM-006** SHOULD: Inject test doubles (NoopMailService, etc.) in ScimApplicationFactory to prevent external side effects during integration tests. + +### Verify + +```bash +# Verify SaveChanges usage in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify async HTTP methods are used with await +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify authentication handler configuration +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges or SaveChangesAsync before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- No race conditions or flaky test failures occur due to persistence timing + + +Claude Code MUST NOT skip or defer verification of these rules during code review of SCIM integration tests. Violations must be identified and corrected before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scim-integration-tests-c5f8.md b/.actual/rules/cross-cutting-scim-integration-tests-c5f8.md new file mode 100644 index 000000000000..423d53ea755d --- /dev/null +++ b/.actual/rules/cross-cutting-scim-integration-tests-c5f8.md @@ -0,0 +1,31 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Scim Integration Tests + +These rules are ALWAYS ACTIVE for all SCIM API integration test files and test infrastructure in the ScimApplicationFactory and related test harnesses. + +### Rules + +- **R-SCIM-001** MUST: SCIM API integration tests MUST use System.Text.Json for serializing request and response payloads + +### Verify + +```bash +# Verify System.Text.Json is imported in SCIM integration tests +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify DatabaseContext.SaveChanges pattern is used for data persistence +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify test authentication handlers use System.Security.Claims +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- JsonSerializerOptions are explicitly configured for SCIM schema compliance (PropertyNamingPolicy, DefaultIgnoreCondition) +- HTTP request/response bodies are serialized using System.Text.Json + + +Clause Code MUST NOT skip or defer verification. All SCIM integration test changes must be verified against these rules before acceptance. Violations require architecture review board approval with documented justification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scim-named-policy-cbc1.md b/.actual/rules/cross-cutting-scim-named-policy-cbc1.md new file mode 100644 index 000000000000..cff5b550c8dc --- /dev/null +++ b/.actual/rules/cross-cutting-scim-named-policy-cbc1.md @@ -0,0 +1,38 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Scim Named Policy + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including startup configuration, middleware pipeline components, and SCIM API controllers. + +### Rules + +- **R-SCIM-001** MUST: The 'Scim' named policy MUST be defined with policy.RequireAuthenticatedUser() in production environments. +- **R-SCIM-002** MUST: All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes MUST enforce the named 'Scim' policy. +- **R-SCIM-003** MUST: Services implementing IScimContext and ICurrentContext interfaces MUST be protected by authorization policy enforcement. +- **R-SCIM-004** MUST: Controllers decorated with authorization policy attributes MUST use the 'Scim' named policy consistently. +- **R-SCIM-005** MUST: app.UseAuthentication() MUST be called before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation. +- **R-SCIM-006** MUST: Authentication schemes MUST be registered before calling AddAuthorization to ensure authentication handlers are available for policy evaluation. +- **R-SCIM-007** SHOULD: Production Scim policies SHOULD include RequireClaim for 'api.scim' scope in addition to RequireAuthenticatedUser(). +- **R-SCIM-008** MAY: Integration test environments MAY use simplified authorization policies with RequireAssertion(a => true) for automated testing without full authentication infrastructure. + +### Verify + +```bash +# Verify AddAuthorization configuration with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify api.scim scope claim requirements +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups are protected by policy enforcement +- Controllers implementing IScimContext and ICurrentContext have authorization policy attributes applied + + +Claude Code MUST NOT skip or defer verification of authorization policy configuration. All SCIM endpoints MUST be verified to have the 'Scim' named policy enforced before accepting pull requests or code changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scim-service-endpoints-f9a4.md b/.actual/rules/cross-cutting-scim-service-endpoints-f9a4.md new file mode 100644 index 000000000000..286f76d64baa --- /dev/null +++ b/.actual/rules/cross-cutting-scim-service-endpoints-f9a4.md @@ -0,0 +1,40 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Scim Service Endpoints + +These rules are ALWAYS ACTIVE for all SCIM service endpoints under the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces, including ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations, authorization policies, and ASP.NET Core authentication middleware configuration. + +### Rules + +- **R-SCIM-001** MUST: SCIM service endpoints MUST register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme as the primary authentication scheme. +- **R-SCIM-002** MUST: Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization(). +- **R-SCIM-003** MUST: Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-004** MUST: Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-005** MUST: Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim'). +- **R-SCIM-006** SHOULD: Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy configuration +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers are isolated +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- ApiKeyAuthenticationHandler implementation properly validates credentials and populates scope claims +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline + + +Clause Code MUST NOT skip or defer verification. All SCIM authentication configuration changes require validation against these rules before merge. Pull requests modifying authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review. Production deployments with test authentication handlers registered trigger automated rollback and incident response. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-scope-based-authorization-bd9c.md b/.actual/rules/cross-cutting-scope-based-authorization-bd9c.md new file mode 100644 index 000000000000..6ed980e38af1 --- /dev/null +++ b/.actual/rules/cross-cutting-scope-based-authorization-bd9c.md @@ -0,0 +1,29 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Scope Based Authorization + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-SCOPE-001** MUST: API scope-based authorization MUST use RequireClaim with JwtClaimTypes.Scope to enforce scope requirements. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + + +Claude Code MUST NOT skip or defer verification. Static code analysis scanning for authorization policy configurations in CI/CD pipeline is mandatory. Security-focused code review checklist requiring verification of authorization policy definitions is mandatory. Automated integration tests validating authorization behavior with valid and invalid tokens are mandatory. CI/CD pipeline MUST fail builds containing permissive authorization policies (RequireAssertion) in production code paths. Security team review is required for any authorization policy changes before merge to main branch. Runtime monitoring MUST alert on authorization failures to detect misconfigured policies in production. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-self-modification-operations-9860.md b/.actual/rules/cross-cutting-self-modification-operations-9860.md new file mode 100644 index 000000000000..a6f6751b7de7 --- /dev/null +++ b/.actual/rules/cross-cutting-self-modification-operations-9860.md @@ -0,0 +1,33 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Self Modification Operations + +These rules are ALWAYS ACTIVE for all API controllers managing organization user operations and collection access within the AdminConsole namespace, specifically for self-modification operations that could enable privilege escalation. + +### Rules + +- **R-SELF-MOD-001** MUST: Self-modification operations MUST check `organizationAbility.AllowAdminAccessToAllCollectionItems` before permitting users to add themselves to collections or groups. + +### Verify + +```bash +# Verify IAuthorizationService is injected in OrganizationUsersController +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' + +# Verify AuthorizeAsync is called for collection modification operations +grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs + +# Verify authorization failures throw NotFoundException +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +# Verify self-modification checks against organizationAbility +grep -r 'AllowAdminAccessToAllCollectionItems' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +``` + +**Accept when:** +- All controllers in `Bit.Api.AdminConsole.Controllers` managing organization users inject `IAuthorizationService` +- All endpoints modifying collection access call `AuthorizeAsync` with appropriate requirements before persistence +- Authorization failures consistently throw `NotFoundException` to prevent enumeration +- Self-modification operations explicitly check `organizationAbility.AllowAdminAccessToAllCollectionItems` before allowing collection or group additions + + +Claude Code MUST NOT skip or defer verification. All four verification commands must pass before accepting changes to organization user self-modification operations. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-self-modification-operations-b5aa.md b/.actual/rules/cross-cutting-self-modification-operations-b5aa.md new file mode 100644 index 000000000000..003ac67df84b --- /dev/null +++ b/.actual/rules/cross-cutting-self-modification-operations-b5aa.md @@ -0,0 +1,37 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Self Modification Operations + +These rules are ALWAYS ACTIVE for all HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups, particularly self-modification operations where users modify their own organization membership or permissions. + +### Rules + +- **R-SELF-MOD-001** MUST_NOT: Self-modification operations MUST_NOT allow users to grant themselves permissions to collections when AllowAdminAccessToAllCollectionItems is disabled. +- **R-SELF-MOD-002** MUST: Perform authorization checks using IAuthorizationService with typed requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) before domain validation logic. +- **R-SELF-MOD-003** MUST: Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence. +- **R-SELF-MOD-004** MUST: For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes. +- **R-SELF-MOD-005** MUST: Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges. +- **R-SELF-MOD-006** SHOULD: Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities. +- **R-SELF-MOD-007** SHOULD: Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections. + +### Verify + +```bash +# Count authorization checks using BulkCollectionOperations +grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l + +# Verify NotFoundException is thrown after authorization checks +grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l + +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers +- Self-modification operations explicitly check AllowAdminAccessToAllCollectionItems before allowing privilege escalation + + +Claude Code MUST NOT skip or defer verification. All rules must be validated through code review, static analysis, and integration testing before accepting changes to organization user management endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-service-controllers-separate-385f.md b/.actual/rules/cross-cutting-service-controllers-separate-385f.md new file mode 100644 index 000000000000..c00c47da703c --- /dev/null +++ b/.actual/rules/cross-cutting-service-controllers-separate-385f.md @@ -0,0 +1,35 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Service Controllers Separate + +These rules are ALWAYS ACTIVE for all Service API controller files that expose HTTP endpoints and coordinate command execution or query operations through dedicated interface abstractions. + +### Rules + +- **R-CQSA-001** MUST: Service API controllers MUST separate command operations from query operations using dedicated interface abstractions (e.g., ISceneExecutor, IDestroySceneCommand, IQueries) rather than performing direct data access. +- **R-CQSA-002** MUST: All API controller action methods MUST use async Task signatures and await command/query interface methods (ExecuteAsync, DestroyAsync, or similar) for all data access operations. +- **R-CQSA-003** MUST: Controllers MUST inject command and query interfaces via constructor dependency injection rather than accessing DbContext or persistence layers directly. +- **R-CQSA-004** SHOULD: Error handling SHOULD distinguish between aggregate failures (batch operations) and single execution failures, providing structured error responses at the API boundary. +- **R-CQSA-005** SHOULD: All asynchronous operations SHOULD follow async-all-the-way patterns without mixing synchronous and asynchronous code paths. + +### Verify + +```bash +# Verify all controller action methods use async Task pattern +grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' + +# Detect direct data access (DbContext, SaveChanges, Query, Execute) in controller classes +grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" + +# Count controller files with async/await patterns and interface method invocations +find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l +``` + +**Accept when:** +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access. +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments). +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar). +- Command and query interfaces are injected via constructor dependency injection in all controller classes. +- Error handling distinguishes between aggregate exceptions (batch operations) and domain-specific exceptions (e.g., SceneExecutionException). + + +Clause Code MUST NOT skip or defer verification. All R-CQSA rules are mandatory for service controller implementations. Violations detected by static analysis or code review MUST be resolved or explicitly exempted with architectural justification before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-service-registration-occur-aab5.md b/.actual/rules/cross-cutting-service-registration-occur-aab5.md new file mode 100644 index 000000000000..4c4642e2ace4 --- /dev/null +++ b/.actual/rules/cross-cutting-service-registration-occur-aab5.md @@ -0,0 +1,38 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Service Registration Occur + +These rules are ALWAYS ACTIVE for all application startup, factory, and service configuration files that register dependencies with the ASP.NET Core dependency injection container. + +### Rules + +- **R-DI-001** SHOULD: Service registration SHOULD occur in factory or startup classes that configure the application host for specific environments. +- **R-DI-002** MUST: All external dependencies MUST be registered via interface abstractions (e.g., IMailService) to enable substitution in test environments. +- **R-DI-003** MUST: Services MUST be registered using IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) rather than direct instantiation. +- **R-DI-004** SHOULD: Test environments SHOULD create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles. +- **R-DI-005** SHOULD: Authentication schemes SHOULD be configured before authorization policies, as policies may depend on authentication scheme configuration. +- **R-DI-006** SHOULD: Complex authorization logic SHOULD be extracted from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability. + +### Verify + +```bash +# Count active dependency injection registrations +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration is present +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Find test factory classes with service collection configuration +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +# Verify no service locator anti-patterns +grep -r 'new.*Service\|ServiceLocator' --include='*.cs' | grep -v '.Test' | grep -v 'comment' | wc -l +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments +- Service locator anti-pattern grep returns zero or only test-related matches + + +Claude Code MUST NOT skip or defer verification. All service registrations MUST be validated to use dependency injection container patterns. Build failures MUST occur when services cannot be resolved from the dependency injection container at application startup. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-services-extend-base-95a6.md b/.actual/rules/cross-cutting-services-extend-base-95a6.md new file mode 100644 index 000000000000..c624b417c527 --- /dev/null +++ b/.actual/rules/cross-cutting-services-extend-base-95a6.md @@ -0,0 +1,36 @@ +# Expose Extended Cache Configuration as Public API Contract: Services Extend Base + +These rules are ALWAYS ACTIVE for all service registration code using distributed Redis caching, cache initialization in Bit.Core.Utilities namespace, IDistributedCache implementations backed by Redis, and service collection extension methods for cache configuration. + +### Rules + +- **R-CACHE-001** MUST: All service registration code use AddExtendedCache instead of direct AddStackExchangeRedisCache calls for distributed Redis caching. +- **R-CACHE-002** MUST: No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions. +- **R-CACHE-003** MUST: Redis connection error logging include cache name context via ILogger.LogError. +- **R-CACHE-004** MAY: Services MAY extend the base ExtendedCacheServiceCollectionExtensions with additional cache-specific configuration options. + +### Verify + +```bash +# Verify AddExtendedCache usage +grep -r 'AddExtendedCache' --include='*.cs' . + +# Detect direct AddStackExchangeRedisCache calls outside approved extension +grep -r 'AddStackExchangeRedisCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions' + +# Verify error logging includes cache name context +grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' . + +# Detect direct ConnectionMultiplexer.Connect outside approved extension +grep -r 'ConnectionMultiplexer\.Connect' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions' +``` + +**Accept when:** +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions +- No direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions + + +Claude Code MUST NOT skip or defer verification. CI pipeline MUST fail if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions. Pull requests with non-compliant cache registration MUST be blocked until migrated to AddExtendedCache. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-services-implement-custom-e177.md b/.actual/rules/cross-cutting-services-implement-custom-e177.md new file mode 100644 index 000000000000..57f945138e02 --- /dev/null +++ b/.actual/rules/cross-cutting-services-implement-custom-e177.md @@ -0,0 +1,29 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Services Implement Custom + +These rules are ALWAYS ACTIVE for all HTTP client implementations in service-oriented architectures integrating with external APIs, third-party services, and distributed system components across Rust and C# runtimes. + +### Rules + +- **R-HTTP-001** MAY: Services MAY implement custom HTTP message handlers for cross-cutting concerns like logging, authentication token injection, or request correlation. + +### Verify + +```bash +# Count AddHttpClient registrations in .NET services +grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l + +# Count direct HttpClient instantiations outside tests +grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l + +# Count safe FFI string marshaling patterns in Rust +grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l +``` + +**Accept when:** +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + + +Claude Code MUST NOT skip or defer verification. Static analysis scanning for direct HttpClient instantiation patterns outside test contexts is mandatory. Code review checklist verification for HTTP client registration is required for all new external service integrations. CI pipeline MUST fail on detection of direct HttpClient instantiation in production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-services-processing-notifications-c775.md b/.actual/rules/cross-cutting-services-processing-notifications-c775.md new file mode 100644 index 000000000000..30bbc65dd59e --- /dev/null +++ b/.actual/rules/cross-cutting-services-processing-notifications-c775.md @@ -0,0 +1,35 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Services Processing Notifications + +These rules are ALWAYS ACTIVE for all implementations of IPushNotificationService interface and push notification processing logic handling Bit.Core.NotificationCenter.Entities, Bit.Core.AdminConsole.Entities, and Bit.Core.Auth.Entities. + +### Rules + +- **R-PUSH-001** MUST: Services processing notifications from multiple domain entities (AdminConsole, Auth, NotificationCenter) MUST apply consistent validation logging patterns across all entity types. +- **R-PUSH-002** MUST: All invalid notification ID scenarios MUST log warning-level events with structured NotificationId parameter using ILogger.LogWarning. +- **R-PUSH-003** MUST: All invalid notification status ID scenarios MUST log warning-level events with structured NotificationId parameter using ILogger.LogWarning. +- **R-PUSH-004** MUST: Pragma warning disable directives MUST be documented with comments explaining their relationship to the logging quality gate. +- **R-PUSH-005** SHOULD: Use ILogger interface with structured logging templates following the pattern: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id). +- **R-PUSH-006** MAY: Implement log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform. + +### Verify + +```bash +# Verify warning-level logging for invalid notification IDs +grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' + +# Verify IPushNotificationService implementations include logger.LogWarning +grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' + +# Verify pragma warning disable directives are present and documented +find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; +``` + +**Accept when:** +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate +- Consistent warning-level logging is applied across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities + + +Claude Code MUST NOT skip or defer verification. Code review rejection is required if validation failures lack warning-level logging with structured parameters. CI pipeline warnings must be addressed if push notification services are modified without corresponding logging verification. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-services-register-multiple-1cc0.md b/.actual/rules/cross-cutting-services-register-multiple-1cc0.md new file mode 100644 index 000000000000..b88dbbbf9c16 --- /dev/null +++ b/.actual/rules/cross-cutting-services-register-multiple-1cc0.md @@ -0,0 +1,38 @@ +# Establish HTTP Client Boundaries for External Service Integration: Services Register Multiple + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations including SCIM endpoints, pricing services, identity providers, and SSO configuration endpoints. + +### Rules + +- **R-HTTP-001** MUST: Use IHttpClientFactory for all HTTP client creation rather than direct `new HttpClient()` instantiation. +- **R-HTTP-002** MUST: Register all HTTP clients in Startup.cs ConfigureServices method using `services.AddHttpClient()` or `services.AddHttpClient(name)` for named clients. +- **R-HTTP-003** MUST: Chain `.AddSsrfProtection()` to HTTP client registrations that process user-supplied URLs or redirects. +- **R-HTTP-004** MUST: Inject IHttpClientFactory into services and call `CreateClient()` or `CreateClient(name)` to obtain configured instances. +- **R-HTTP-005** MAY: Services MAY register multiple named HTTP clients with different configurations for different external service endpoints. +- **R-HTTP-006** SHOULD: Establish naming conventions and configuration templates for common external service types to prevent configuration drift. +- **R-HTTP-007** SHOULD: Implement startup validation to detect duplicate or misconfigured client registrations. +- **R-HTTP-008** SHOULD: Include code review checklist verification requiring SSRF protection for all AddHttpClient registrations. + +### Verify + +```bash +# Check for direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are present +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct `new HttpClient()` instantiations outside documented legacy exceptions (EXC-001, EXC-002) +- All HTTP clients that accept user-supplied URLs include `AddSsrfProtection()` in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- Named client registrations follow established naming conventions and configuration templates +- Startup validation detects and prevents duplicate or misconfigured client registrations + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations MUST pass code review checklist verification. Direct HttpClient instantiation patterns MUST be blocked until refactored to use IHttpClientFactory. Missing SSRF protection on user-facing endpoints MUST trigger security review and block deployment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-shared-cryptographic-resources-16aa.md b/.actual/rules/cross-cutting-shared-cryptographic-resources-16aa.md new file mode 100644 index 000000000000..2dee7486347b --- /dev/null +++ b/.actual/rules/cross-cutting-shared-cryptographic-resources-16aa.md @@ -0,0 +1,46 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Shared Cryptographic Resources + +These rules are ALWAYS ACTIVE for all Rust SDK FFI functions in `util/RustSdk/rust/src/lib.rs` that handle cryptographic key material, public key generation APIs, cipher and RSA key data structures exposed across FFI boundaries, and test infrastructure requiring mock implementations of cryptographic primitives. + +### Rules + +- **R-CRYPTO-001** MUST: All data structures crossing FFI boundaries use `#[repr(C)]` attribute to ensure stable memory layout. +- **R-CRYPTO-002** MUST: All public FFI functions handling key material use `std::ffi` types (`c_char`, `CStr`, `CString`) with explicit validation. +- **R-CRYPTO-003** MUST: All `CStr::from_ptr` calls are wrapped in unsafe blocks with explicit null pointer checks and UTF-8 validation. +- **R-CRYPTO-004** MUST: Memory management functions (`free_c_string`) are provided and documented for all FFI-allocated strings, specifying which side (Rust or C) owns allocated memory. +- **R-CRYPTO-005** MUST: FFI functions return error codes to C callers instead of panicking on invalid UTF-8 input. +- **R-CRYPTO-006** SHOULD: Shared cryptographic resources (RSA_POOL) be modeled as centralized singletons or pools to avoid redundant key generation overhead. +- **R-CRYPTO-007** SHOULD: Mock traits (e.g., `CipherOps`, `RsaKeyOps`) be defined so both production and test implementations can satisfy them, using dependency injection or feature flags to select implementations. +- **R-CRYPTO-008** SHOULD: Integration tests using real cryptographic operations be maintained alongside unit tests with mocks to verify dual implementation correctness. +- **R-CRYPTO-009** MAY: Opaque pointer handles be used at FFI boundary only when FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck. + +### Verify + +```bash +# Verify public key generation functions exist +grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' + +# Confirm FFI type usage +grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +# Run tests with mock implementations +cargo test --package bitwarden-crypto --lib -- --test-threads=1 + +# Verify #[repr(C)] on FFI-crossing structures +grep -B1 'pub struct' util/RustSdk/rust/src/lib.rs | grep -c 'repr(C)' + +# Verify memory management functions are documented +grep -A5 'free_c_string' util/RustSdk/rust/src/lib.rs | grep -c 'ownership\|Rust\|C' +``` + +**Accept when:** +- All public FFI functions handling key material use `std::ffi` types (`c_char`, `CStr`, `CString`) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (`free_c_string`) are provided and documented for all FFI-allocated strings +- All data structures crossing FFI boundaries have `#[repr(C)]` attribute +- All `CStr::from_ptr` calls are wrapped in unsafe blocks with null pointer checks +- Integration tests using real cryptographic operations pass alongside unit tests with mocks + + +Claude Code MUST NOT skip or defer verification. CI build MUST fail if FFI functions lack required validation or memory management functions. Pull requests adding new FFI entry points MUST require security team approval. Runtime panics in FFI code MUST trigger incident review and post-mortem analysis. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-string-data-crossing-3353.md b/.actual/rules/cross-cutting-string-data-crossing-3353.md new file mode 100644 index 000000000000..a4a067660c14 --- /dev/null +++ b/.actual/rules/cross-cutting-string-data-crossing-3353.md @@ -0,0 +1,36 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: String Data Crossing + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs, cryptographic key generation and management functions exposed to C, string parameters and return values crossing the Rust/C FFI boundary, and memory deallocation functions for Rust-allocated resources. + +### Rules + +- **R-FFI-001** MUST: All string data crossing the FFI boundary MUST use std::ffi::CString for Rust-to-C transfers and std::ffi::CStr for C-to-Rust transfers. +- **R-FFI-002** MUST: All public FFI functions returning strings MUST use CString::into_raw() to transfer ownership and document the requirement to call free_c_string. +- **R-FFI-003** MUST: A free_c_string function MUST exist and be exported in the public API to reclaim ownership using CString::from_raw() before deallocation. +- **R-FFI-004** MUST: Input validation MUST check for null pointers using .is_null() before dereferencing c_char pointers from C. +- **R-FFI-005** MUST: Documentation MUST include examples of correct string ownership transfer and deallocation for all FFI functions. +- **R-FFI-006** MAY: Static string literals that do not require deallocation are excepted from R-FFI-001 (EXC-001). + +### Verify + +```bash +# Count CString usage patterns in FFI code +grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l + +# Verify public FFI functions returning c_char +grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs + +# Verify free_c_string function exists +grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs +``` + +**Accept when:** +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation +- No raw c_char pointers are returned without corresponding deallocation functions + + +Clause Code MUST NOT skip or defer verification. Code review MUST check CString usage patterns in FFI functions. Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) MUST pass. Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) MUST pass in CI pipeline. Security audit of FFI boundary code MUST be completed during release cycles. CI build MUST fail if FFI functions return raw pointers without corresponding deallocation functions. Code review MUST block merge if FFI string handling lacks proper documentation. Memory sanitizer failures in CI MUST be resolved before merge. Security team escalation is required for violations in cryptographic key handling code. Exceptions MUST be documented in code comments with reference to EXC-001 and require security team approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-string-validation-failures-12ca.md b/.actual/rules/cross-cutting-string-validation-failures-12ca.md new file mode 100644 index 000000000000..de6d8583370b --- /dev/null +++ b/.actual/rules/cross-cutting-string-validation-failures-12ca.md @@ -0,0 +1,38 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: String Validation Failures + +These rules are ALWAYS ACTIVE for all public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers, functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey), and any function marked with #[no_mangle] or extern "C" that accepts string parameters. + +### Rules + +- **R-FFI-001** MUST: String validation failures at FFI boundaries MUST return error codes or null pointers rather than panicking. +- **R-FFI-002** MUST: All extern "C" functions accepting c_char pointers MUST use CStr::from_ptr for validation within an unsafe block. +- **R-FFI-003** MUST: All extern "C" functions returning strings MUST use CString::into_raw for safe memory transfer to the caller. +- **R-FFI-004** MUST: Validation of c_char pointers MUST occur before any cryptographic operations or sensitive processing. +- **R-FFI-005** MUST: The free_c_string function MUST be implemented as: unsafe { CString::from_raw(ptr) } to reclaim and drop memory. +- **R-FFI-006** SHOULD: Use Result return types with error codes mapped to C-compatible integers for validation failures. +- **R-FFI-007** SHOULD: Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements. + +### Verify + +```bash +# Count FFI functions with c_char parameters +grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l + +# Count CStr/CString usage in FFI code +grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l + +# Check for unsafe pointer dereference warnings +cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' +``` + +**Accept when:** +- All extern "C" functions accepting c_char pointers use CStr::from_ptr for validation +- All extern "C" functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations +- No null pointer dereferences occur without prior null checks +- Memory ownership is clearly documented for all returned CString pointers + + +Claude Code MUST NOT skip or defer verification. All FFI string validation rules are security-critical and MUST be verified before accepting changes to FFI boundary functions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-swagger-openapi-document-b183.md b/.actual/rules/cross-cutting-swagger-openapi-document-b183.md new file mode 100644 index 000000000000..08af47e8fb7e --- /dev/null +++ b/.actual/rules/cross-cutting-swagger-openapi-document-b183.md @@ -0,0 +1,36 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Swagger Openapi Document + +These rules are ALWAYS ACTIVE for all Microsoft.AspNetCore.Mvc controller classes and their HTTP action methods, as well as Swagger/OpenAPI document configuration. + +### Rules + +- **R-AUTHZ-001** SHOULD: Swagger/OpenAPI document filters SHOULD validate that operation IDs are unique to prevent duplicate endpoint definitions. +- **R-AUTHZ-002** MUST: All public HTTP action methods (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) on controllers MUST have appropriate authorization attributes at class level ([Authorize]) or method level. +- **R-AUTHZ-003** MUST: Unit tests using reflection MUST systematically verify that all HTTP action methods have appropriate authorization attributes before deployment. +- **R-AUTHZ-004** SHOULD: Test helpers SHOULD use the ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern to validate authorization configuration. +- **R-AUTHZ-005** SHOULD: Swagger configuration SHOULD apply CheckDuplicateOperationIdsDocumentFilter to catch duplicate operation IDs at application startup or in tests. +- **R-AUTHZ-006** MAY: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) MAY be marked with [AllowAnonymous] attribute with documented security review. + +### Verify + +```bash +# Count authorization test helper usage +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run authorization-specific unit tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes on controllers +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- Swagger/OpenAPI document filters validate unique operation IDs without conflicts +- Any [AllowAnonymous] endpoints are documented with security review rationale + + +Claude Code MUST NOT skip or defer verification. Authorization attribute validation MUST execute in CI pipeline before code reaches production. Build failures from missing authorization attributes MUST block pull request merges. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-configuration-f8dc.md b/.actual/rules/cross-cutting-test-authentication-configuration-f8dc.md new file mode 100644 index 000000000000..c1a7f72dd042 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-configuration-f8dc.md @@ -0,0 +1,44 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Configuration + +These rules are ALWAYS ACTIVE for all test projects and integration test infrastructure code that configures authentication middleware for ASP.NET Core applications. + +### Rules + +- **R-TESTAUTH-001** MAY: Test authentication configuration MAY be combined with AddAuthorization() to configure test-specific authorization policies. +- **R-TESTAUTH-002** MUST: Test authentication handlers MUST extend AuthenticationHandler with HandleAuthenticateAsync() implementations that return deterministic claims. +- **R-TESTAUTH-003** MUST: Test authentication schemes MUST be registered using AddAuthentication() in test startup or factory classes, with scheme names matching the identity scheme name in ClaimsIdentity. +- **R-TESTAUTH-004** MUST: Test authentication handlers MUST return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims (e.g., ClaimTypes.Name, organization identifiers). +- **R-TESTAUTH-005** MUST: Test authentication configuration MUST be isolated to test environments and MUST NOT be deployed to production code paths. +- **R-TESTAUTH-006** SHOULD: Test authentication handlers SHOULD be reviewed and updated when authorization policies change to prevent stale claim sets. +- **R-TESTAUTH-007** SHOULD: Separate end-to-end tests with production authentication schemes SHOULD be maintained against test identity providers to validate production authentication behavior. + +### Verify + +```bash +# Detect test authentication handler implementations +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Detect AddAuthentication registration in test code +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Detect HandleAuthenticateAsync implementations +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Detect AuthenticateResult.Success usage +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +# Verify test authentication is not in production code +grep -r "AddAuthentication.*Test" --include="*.cs" --exclude-dir="*Test*" --exclude-dir="*test*" +``` + +**Accept when:** +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims +- Authorization policies are configured after authentication registration in test startup +- Test authentication configuration is isolated to test environments and not present in production code paths +- Test claims include organization identifiers and other claims required by authorization policies + + +Claude Code MUST NOT skip or defer verification. All test authentication handler implementations MUST be reviewed to ensure they extend AuthenticationHandler, implement HandleAuthenticateAsync() with deterministic claims, and are registered only in test environments. CI pipeline verification commands MUST execute successfully before accepting test authentication configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-handlers-98aa.md b/.actual/rules/cross-cutting-test-authentication-handlers-98aa.md new file mode 100644 index 000000000000..d9bec68e126c --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-handlers-98aa.md @@ -0,0 +1,43 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Handlers + +These rules are ALWAYS ACTIVE for all test authentication handler implementations and test startup/factory classes that configure authentication middleware in integration test projects. + +### Rules + +- **R-AUTH-001** MUST: Test authentication handlers MUST extend AuthenticationHandler and override HandleAuthenticateAsync(). +- **R-AUTH-002** MUST: Test authentication handlers MUST return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers). +- **R-AUTH-003** MUST: Test startup or factory classes MUST call AddAuthentication() to register test authentication schemes during service configuration. +- **R-AUTH-004** MUST: Test authentication scheme names MUST match the identity scheme name in the ClaimsIdentity to ensure proper authentication pipeline integration. +- **R-AUTH-005** MUST: Authorization policies MUST be configured after authentication registration to ensure policies can evaluate claims provided by test authentication handlers. +- **R-AUTH-006** MUST: Test authentication schemes MUST be isolated to test environments only and MUST NOT be registered in production code paths. + +### Verify + +```bash +# Detect test authentication handler implementations +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Detect HandleAuthenticateAsync implementations in test code +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Detect AddAuthentication calls in test startup/factory classes +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Detect AuthenticateResult.Success usage in test authentication handlers +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +# Verify test authentication handlers are not in production code paths +grep -r "AuthenticationHandler" --include="*.cs" --exclude="*Test*.cs" --exclude="*Factory*.cs" | grep -v "//" +``` + +**Accept when:** +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims +- Test authentication scheme names match the identity scheme name in ClaimsIdentity +- Authorization policies are configured after authentication registration +- Test authentication handlers are isolated to test environments and not present in production code paths + + +Claude Code MUST NOT skip or defer verification of test authentication handler implementations. All R-AUTH rules MUST be verified before accepting test authentication configuration changes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-handlers-9daa.md b/.actual/rules/cross-cutting-test-authentication-handlers-9daa.md new file mode 100644 index 000000000000..6fd41811428d --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-handlers-9daa.md @@ -0,0 +1,41 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Test Authentication Handlers + +These rules are ALWAYS ACTIVE for all SCIM API integration test files in the `bitwarden_license/test/Scim.IntegrationTest/` directory, particularly those implementing test authentication handlers, HTTP request/response serialization, and Entity Framework data persistence patterns. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD: Test authentication handlers SHOULD use System.Security.Claims for constructing test user identities. +- **R-SCIM-AUTH-002** MUST: All SCIM integration test files MUST import System.Text.Json for JSON serialization of HTTP request and response bodies. +- **R-SCIM-AUTH-003** MUST: Data persistence operations MUST use DatabaseContext.SaveChanges pattern for SCIM resource lifecycle management. +- **R-SCIM-AUTH-004** SHOULD: JsonSerializerOptions SHOULD be configured explicitly in the test factory with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema compliance. +- **R-SCIM-AUTH-005** SHOULD: Test requests SHOULD include User-Agent headers (e.g., 'Okta') to simulate real SCIM client behavior. +- **R-SCIM-AUTH-006** SHOULD: DatabaseContext SHOULD be properly scoped per test to avoid state leakage between test cases. +- **R-SCIM-AUTH-007** MAY: Read-only test scenarios MAY use AsNoTracking to reduce Entity Framework change tracking overhead. + +### Verify + +```bash +# Verify System.Text.Json usage in SCIM integration tests +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify DatabaseContext.SaveChanges pattern usage +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify System.Security.Claims usage in test authentication handlers +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +# Verify ScimApplicationFactory pattern is used +grep -r 'ScimApplicationFactory' bitwarden_license/test/Scim.IntegrationTest/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- ScimApplicationFactory is used as the test harness for HTTP serialization +- JsonSerializerOptions are explicitly configured in the test factory +- User-Agent headers are set in test requests to simulate SCIM clients + + +Claude Code MUST NOT skip or defer verification of these rules. All SCIM integration test changes MUST be verified against these criteria before acceptance. Violations require architecture review and documented exceptions. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-handlers-9e7c.md b/.actual/rules/cross-cutting-test-authentication-handlers-9e7c.md new file mode 100644 index 000000000000..0c9fd5596fb1 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-handlers-9e7c.md @@ -0,0 +1,40 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Test Authentication Handlers + +These rules are ALWAYS ACTIVE for all files matching the configured scope, particularly test infrastructure, factory classes, and authentication handler implementations. + +### Rules + +- **R-DI-001** MAY: Test authentication handlers MAY use hardcoded claims and identities to simulate authenticated users with specific permissions. +- **R-DI-002** MUST: Register services in ConfigureServices or equivalent factory methods using IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient). +- **R-DI-003** MUST: Use interface abstractions for all external dependencies to enable substitution in test environments. +- **R-DI-004** SHOULD: Create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles for test environments. +- **R-DI-005** SHOULD: Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration. +- **R-DI-006** SHOULD: Extract complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability. +- **R-DI-007** MUST NOT: Use service locator pattern with manual instantiation instead of dependency injection container. +- **R-DI-008** MUST NOT: Directly instantiate concrete classes in tests without interface abstractions. + +### Verify + +```bash +# Check for active use of dependency injection patterns +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration is present +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Find test factory classes that configure service registrations +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +# Verify no service locator anti-patterns +grep -r 'ServiceLocator\|GetService' --include='*.cs' | grep -v 'IServiceProvider' | wc -l +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments +- Service locator anti-pattern grep returns zero or minimal results + + +Claude Code MUST NOT skip or defer verification. All rules MUST be validated during code review and integration test execution. Service resolution failures at application startup constitute build failures. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-handlers-c778.md b/.actual/rules/cross-cutting-test-authentication-handlers-c778.md new file mode 100644 index 000000000000..3102e60d0360 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-handlers-c778.md @@ -0,0 +1,44 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Handlers + +These rules are ALWAYS ACTIVE for all test authentication handler implementations and test startup/factory classes that configure authentication middleware for integration testing. + +### Rules + +- **R-AUTH-001** MUST: Test authentication handlers MUST return AuthenticateResult.Success() with a ClaimsPrincipal containing test claims. +- **R-AUTH-002** MUST: Test authentication handlers MUST extend AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock. +- **R-AUTH-003** MUST: Test authentication handlers MUST override HandleAuthenticateAsync() to return deterministic claims including test-appropriate identifiers (e.g., organization identifiers, user names). +- **R-AUTH-004** MUST: Test startup or factory classes MUST call AddAuthentication() to register test authentication schemes during service configuration. +- **R-AUTH-005** MUST: Test authentication scheme names MUST match the identity scheme name in the ClaimsIdentity to ensure proper claim evaluation. +- **R-AUTH-006** MUST: Authorization policies MUST be configured after authentication registration to ensure policies can evaluate claims provided by test authentication handlers. +- **R-AUTH-007** MUST: Test authentication schemes MUST be isolated to test environments only and MUST NOT be registered in production code paths. + +### Verify + +```bash +# Detect test authentication handler implementations +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Detect AddAuthentication calls in test infrastructure +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Detect HandleAuthenticateAsync implementations +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Detect AuthenticateResult.Success usage +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +# Verify no test authentication in production paths +grep -r "AddAuthentication.*Test" --include="*.cs" --exclude-dir="*Test*" --exclude-dir="*test*" +``` + +**Accept when:** +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims +- Authorization policies are configured after authentication registration +- Test authentication schemes are isolated to test environments and not present in production code paths +- Integration tests execute with deterministic authentication state without external identity provider dependencies + + +Claude Code MUST NOT skip or defer verification of test authentication handler implementations. All grep-based verification commands MUST be executed to confirm compliance with R-AUTH-001 through R-AUTH-007. Code review of test authentication handler implementations is mandatory before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-handlers-d009.md b/.actual/rules/cross-cutting-test-authentication-handlers-d009.md new file mode 100644 index 000000000000..d31b96fedab1 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-handlers-d009.md @@ -0,0 +1,45 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Test Authentication Handlers + +These rules are ALWAYS ACTIVE for all SCIM service authentication handlers, authorization policies, and integration test authentication implementations within the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces. + +### Rules + +- **R-SCIM-AUTH-001** MUST: Test authentication handlers MUST use System.Security.Claims.ClaimsIdentity with organizational admin claims for integration test scenarios. +- **R-SCIM-AUTH-002** MUST: All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme. +- **R-SCIM-AUTH-003** MUST: Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims. +- **R-SCIM-AUTH-004** MUST: Test authentication handlers MUST be isolated to test assemblies and inherit from AuthenticationHandler with proper claims population. +- **R-SCIM-AUTH-005** MUST: Authentication middleware MUST be registered before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization(). +- **R-SCIM-AUTH-006** MUST: ApiKeyAuthenticationHandler MUST validate API keys against secure storage and populate ClaimsPrincipal with required scope claims including 'api.scim'. +- **R-SCIM-AUTH-007** MUST: Test authentication handlers MUST use clear naming conventions (e.g., TestAuthHandler) to prevent production deployment. +- **R-SCIM-AUTH-008** MUST: Authorization policies MUST be configured in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim'). +- **R-SCIM-AUTH-009** MUST: Organizational context claims (e.g., 'orgadmin' with organization ID) MUST be included in authentication tickets to support multi-tenant authorization logic. +- **R-SCIM-AUTH-010** MUST: Production deployments with test authentication handlers registered MUST trigger automated rollback and incident response. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policy scope enforcement +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handler isolation +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Execute integration test suite +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- ApiKeyAuthenticationHandler implementation properly validates credentials and populates scope claims +- Organizational context claims are present in authentication tickets for multi-tenant scenarios +- Authentication middleware is registered before authorization middleware in the ASP.NET Core pipeline + + +Claude Code MUST NOT skip or defer verification. Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review. Production deployments with test authentication handlers registered trigger automated rollback and incident response. Authorization policy changes that weaken scope claim requirements require security team approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-schemes-58ef.md b/.actual/rules/cross-cutting-test-authentication-schemes-58ef.md new file mode 100644 index 000000000000..3e6175eb1557 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-schemes-58ef.md @@ -0,0 +1,34 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Test Authentication Schemes + +These rules are ALWAYS ACTIVE for all SCIM service authentication handlers, authorization policies, and integration test authentication schemes in the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD: Test authentication schemes SHOULD include organizational context claims (e.g., 'orgadmin' with organization ID) to simulate multi-tenant scenarios. + +### Verify + +```bash +# Verify API key authentication scheme registration +grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ + +# Verify authorization policies enforce api.scim scope +grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ + +# Verify test authentication handlers are properly isolated +grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ + +# Run integration tests to validate authentication and authorization +dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build +``` + +**Accept when:** +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement +- Test authentication handlers include organizational context claims for multi-tenant scenario simulation + + +Clause Code MUST NOT skip or defer verification of authentication scheme registration, authorization policy enforcement, and test handler isolation before approving changes to SCIM authentication configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authentication-schemes-ba44.md b/.actual/rules/cross-cutting-test-authentication-schemes-ba44.md new file mode 100644 index 000000000000..567454deb1a7 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authentication-schemes-ba44.md @@ -0,0 +1,43 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Schemes + +These rules are ALWAYS ACTIVE for all integration test files and test factory/startup classes that configure authentication middleware for ASP.NET Core test environments. + +### Rules + +- **R-TESTAUTH-001** SHOULD: Test authentication schemes SHOULD use a distinct scheme name (e.g., "Test") to differentiate from production schemes. +- **R-TESTAUTH-002** MUST: Test authentication handlers MUST extend AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock. +- **R-TESTAUTH-003** MUST: Test authentication handlers MUST override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers). +- **R-TESTAUTH-004** MUST: Test startup or factory classes MUST register test authentication schemes using AddAuthentication("Test") to ensure the scheme name matches the identity scheme name in the ClaimsIdentity. +- **R-TESTAUTH-005** MUST: Authorization policies MUST be configured after authentication registration to ensure policies can evaluate claims provided by test authentication handlers. +- **R-TESTAUTH-006** MUST: Test authentication schemes MUST only be registered in test environments and MUST NOT be deployed to production code paths. + +### Verify + +```bash +# Detect AddAuthentication usage in test files +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Detect AuthenticationHandler implementations in test files +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Detect HandleAuthenticateAsync implementations in test files +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Detect AuthenticateResult.Success usage in test files +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +# Verify test authentication handlers are not in production code paths +grep -r "AddAuthentication.*Test" --include="*.cs" --exclude-dir="*Test*" --exclude-dir="*test*" | grep -v "//" +``` + +**Accept when:** +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes with a distinct test scheme name +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims +- Authorization policies are configured after authentication registration in test startup +- Test authentication schemes are isolated to test environments and not present in production code paths +- Integration tests execute with deterministic authentication state and validate authorization policies through the ASP.NET Core authentication pipeline + + +Claude Code MUST NOT skip or defer verification of test authentication handler implementations, AddAuthentication() registration patterns, and environment-specific configuration isolation. Code review and CI pipeline verification commands are mandatory before accepting test authentication configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-authorization-policies-9816.md b/.actual/rules/cross-cutting-test-authorization-policies-9816.md new file mode 100644 index 000000000000..7700d5b8ff82 --- /dev/null +++ b/.actual/rules/cross-cutting-test-authorization-policies-9816.md @@ -0,0 +1,35 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Authorization Policies + +These rules are ALWAYS ACTIVE for all SCIM integration tests in `bitwarden_license/test/Scim.IntegrationTest/` and the `ScimApplicationFactory` test infrastructure. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD: Test authorization policies SHOULD use RequireAssertion for flexible test scenario configuration. +- **R-SCIM-AUTH-002** MUST: Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests. +- **R-SCIM-AUTH-003** MUST: Use async/await consistently for both SaveChangesAsync() and HTTP client methods (GetAsync, PostAsync, PutAsync, PatchAsync) to maintain proper execution order. +- **R-SCIM-AUTH-004** MUST: Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data. +- **R-SCIM-AUTH-005** SHOULD: Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests. + +### Verify + +```bash +# Verify SaveChanges usage in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Count async HTTP operations +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify test authentication configuration +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- RequireAssertion is used in authorization policy configuration for test scenarios +- Test doubles (NoopMailService, etc.) are injected in ScimApplicationFactory + + +Clause Code MUST NOT skip or defer verification. All integration tests MUST demonstrate explicit SaveChanges coordination with async HTTP operations and claims-based authentication configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-claims-include-d13f.md b/.actual/rules/cross-cutting-test-claims-include-d13f.md new file mode 100644 index 000000000000..7574068d9d3e --- /dev/null +++ b/.actual/rules/cross-cutting-test-claims-include-d13f.md @@ -0,0 +1,33 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Claims Include + +These rules are ALWAYS ACTIVE for all integration test files, test factories, and test authentication handler implementations in the project. + +### Rules + +- **R-TEST-AUTH-001** SHOULD: Test claims SHOULD include organization identifiers and user context required by authorization policies. + +### Verify + +```bash +# Detect test authentication handler implementations +grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" + +# Verify AuthenticationHandler extension pattern +grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" + +# Confirm HandleAuthenticateAsync override +grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" + +# Verify success result pattern +grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" +``` + +**Accept when:** +- Test projects contain classes extending `AuthenticationHandler` with `HandleAuthenticateAsync()` implementations +- Test startup or factory classes call `AddAuthentication()` to register authentication schemes +- Test authentication handlers return `AuthenticateResult.Success()` with `ClaimsPrincipal` containing test-appropriate claims including organization identifiers +- Test claims include user context (e.g., `ClaimTypes.Name`, organization identifiers) required by authorization policies + + +Claude Code MUST NOT skip or defer verification of test authentication handler implementations. All integration tests MUST authenticate requests through the ASP.NET Core authentication pipeline using deterministic test claims that satisfy authorization policy requirements. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-code-define-c095.md b/.actual/rules/cross-cutting-test-code-define-c095.md new file mode 100644 index 000000000000..f2fd8002444c --- /dev/null +++ b/.actual/rules/cross-cutting-test-code-define-c095.md @@ -0,0 +1,40 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Test Code Define + +These rules are ALWAYS ACTIVE for all Rust SDK modules in `util/RustSdk/rust/src/` containing cryptographic test fixtures, test helper modules that provide mock cryptographic material for integration tests, and CI/CD verification scripts that scan for hardcoded cryptographic material. + +### Rules + +- **R-TEST-001** MUST: All hardcoded RSA private keys used in tests be defined as constants following the naming pattern `_FAKE_RSA_KEY_N` (where N is a numeric index 0-4 or higher for specialized scenarios). +- **R-TEST-002** MUST: All `_FAKE_RSA_KEY_*` constants be consolidated into a dedicated test fixtures module or `rsa_keys.rs` file to create a single audit point. +- **R-TEST-003** MUST: All `_FAKE_RSA_KEY_*` constants use PEM-encoded PKCS#8 format for RSA private keys. +- **R-TEST-004** MUST: No references to `_FAKE_RSA_KEY_*` constants exist outside `#[cfg(test)]` blocks, test-only modules, or the `rsa_keys.rs` file. +- **R-TEST-005** MUST: Each `_FAKE_RSA_KEY_*` constant include inline documentation explaining its intended test scenario. +- **R-TEST-006** MAY: Test code MAY define additional fake key constants following the same naming pattern for specialized test scenarios requiring more than 5 key pairs. +- **R-TEST-007** SHOULD: CI pipeline include automated checks that fail builds if production code references test key constants. +- **R-TEST-008** SHOULD: Pre-commit hooks grep for `_FAKE_RSA_KEY_` references outside test contexts and reject commits that violate this rule. + +### Verify + +```bash +# Check for production references to fake RSA keys outside test contexts +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' + +# Validate RSA key validation tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' + +# Verify all 5 fake keys are present with correct format +rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' +``` + +**Accept when:** +- All `_FAKE_RSA_KEY_*` constants are defined in `rsa_keys.rs` with `const` visibility and PEM PKCS#8 format +- No references to `_FAKE_RSA_KEY_*` exist outside `#[cfg(test)]` blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario +- Grep verification command returns no production references +- RSA key validation tests pass successfully +- All 5 (or more for specialized scenarios) fake keys are present with correct PEM format + + +Claude Code MUST NOT skip or defer verification. All rules R-TEST-001 through R-TEST-008 are mandatory for cryptographic test fixtures in the Rust SDK. Violations must be caught by pre-commit hooks and CI/CD checks before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-code-exercising-1293.md b/.actual/rules/cross-cutting-test-code-exercising-1293.md new file mode 100644 index 000000000000..dd96fad7c366 --- /dev/null +++ b/.actual/rules/cross-cutting-test-code-exercising-1293.md @@ -0,0 +1,36 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Test Code Exercising + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop test suites. + +### Rules + +- **R-FAKE-RSA-001** MUST: Test code exercising RSA cryptographic operations in public API protocols MUST use embedded fake RSA keys with the naming pattern `_FAKE_RSA_KEY_N` where N is a zero-indexed integer. +- **R-FAKE-RSA-002** MUST: Fake RSA keys MUST be placed in a dedicated test fixtures module (e.g., `src/test_fixtures/rsa_keys.rs`) with clear documentation that keys are for testing only. +- **R-FAKE-RSA-003** MUST: Each fake RSA key block MUST include a comment header explaining it is a test fixture and must never be used in production. +- **R-FAKE-RSA-004** MUST: Static analysis checks MUST fail if `_FAKE_RSA_KEY_` pattern usage is detected outside test modules or in production code paths. +- **R-FAKE-RSA-005** SHOULD: C# test code consuming the Rust SDK via csbindgen SHOULD reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. +- **R-FAKE-RSA-006** SHOULD: Developers SHOULD document the purpose of each fake key if they represent specific test scenarios (e.g., `_FAKE_RSA_KEY_EXPIRED` for expiration testing). + +### Verify + +```bash +# Verify no fake keys appear in production code (outside test modules) +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify at least 5 distinct fake RSA keys are available +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' +``` + +**Accept when:** +- All test code using RSA operations references `_FAKE_RSA_KEY_N` constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Static analysis checks confirm no `_FAKE_RSA_KEY_` patterns exist in non-test files + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis checks MUST fail if fake key patterns appear in production code paths. Code review MUST block merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow the naming convention. Security team notification MUST be triggered for any violation detected in production branches. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-code-requiring-7fee.md b/.actual/rules/cross-cutting-test-code-requiring-7fee.md new file mode 100644 index 000000000000..bdea074d221e --- /dev/null +++ b/.actual/rules/cross-cutting-test-code-requiring-7fee.md @@ -0,0 +1,40 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Code Requiring + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK. + +### Rules + +- **R-CRYPTO-001** MUST: Test code requiring RSA key fixtures MUST use embedded string constants containing PEM-encoded private keys rather than generating keys at runtime or loading from external files. +- **R-CRYPTO-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` annotation or within `mod tests` blocks to ensure test-only compilation. +- **R-CRYPTO-003** MUST: Fake key constants MUST use descriptive names following the pattern `_FAKE_RSA_KEY_N` where N is a sequential number (0-4+). +- **R-CRYPTO-004** MUST: No references to `_FAKE_RSA_KEY_` constants MUST appear in production code paths outside test modules. +- **R-CRYPTO-005** SHOULD: At least 5 distinct fake RSA key constants SHOULD be available in `util/RustSdk/rust/src/rsa_keys.rs` with sequential numbering to support tests requiring multiple distinct keys. +- **R-CRYPTO-006** SHOULD: Fake key constants SHOULD contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-CRYPTO-007** SHOULD: Module-level comments SHOULD document the key generation parameters (algorithm, key size, format) for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Count PEM private key blocks in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Verify rsa_keys tests execute successfully +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +# Verify all fake key constants are properly scoped +grep -B5 '_FAKE_RSA_KEY_' util/RustSdk/rust/src/rsa_keys.rs | grep -E '#\[cfg\(test\)\]|mod tests' || echo 'Scope verification needed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in `util/RustSdk/rust/src/rsa_keys.rs` with sequential numbering +- No references to `_FAKE_RSA_KEY_` constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries +- Module-level comments document key generation parameters (algorithm, key size, format) + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting changes to test cryptographic fixtures. Code review MUST confirm test fixtures are properly scoped with conditional compilation guards. Security team review is required for any exceptions involving cryptographic test patterns. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-code-use-30b7.md b/.actual/rules/cross-cutting-test-code-use-30b7.md new file mode 100644 index 000000000000..6287ca6bda4c --- /dev/null +++ b/.actual/rules/cross-cutting-test-code-use-30b7.md @@ -0,0 +1,35 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Code Use + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in util/RustSdk/rust/src/ and related test modules. + +### Rules + +- **R-CRYPTO-TEST-001** MAY: Test code MAY use std::ffi types (c_char, CStr, CString) to validate FFI boundaries with embedded key material. +- **R-CRYPTO-TEST-002** MUST: All fake RSA key constants be defined in test-only modules with #[cfg(test)] or within mod tests blocks. +- **R-CRYPTO-TEST-003** MUST: Fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-CRYPTO-TEST-004** MUST: No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules. +- **R-CRYPTO-TEST-005** SHOULD: Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys. +- **R-CRYPTO-TEST-006** SHOULD: Define fake key constants with descriptive names and document key generation parameters in module-level comments. + +### Verify + +```bash +# Check for production usage of fake RSA keys +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Count embedded private keys in test fixtures +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Verify test execution +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for test code using embedded cryptographic fixtures. Violations in production code paths trigger immediate CI failure and security review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-configure-a1e8.md b/.actual/rules/cross-cutting-test-environments-configure-a1e8.md new file mode 100644 index 000000000000..39b96154bd0a --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-configure-a1e8.md @@ -0,0 +1,35 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Test Environments Configure + +These rules are ALWAYS ACTIVE for all ASP.NET Core MVC and API controllers requiring authorization, authorization handlers implementing IAuthorizationHandler or AuthorizationHandler, service configuration in Startup or Program.cs registering authorization policies, and integration test factories configuring test authentication and authorization schemes. + +### Rules + +- **R-AUTH-001** SHOULD: Test environments SHOULD configure authorization policies with RequireAssertion to enable controlled test scenarios. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Verify AddAuthorization is registered +grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' + +# Count authorization handler implementations +grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l +``` + +**Accept when:** +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration +- Public endpoints are explicitly marked with [AllowAnonymous] attribute +- Authorization failures throw NotFoundException to prevent information disclosure + + +Claude Code MUST NOT skip or defer verification. All protected endpoints MUST enforce authorization using IAuthorizationService. Test environments MUST configure policies with RequireAssertion. Violations are treated as critical security defects requiring immediate remediation. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-define-bd63.md b/.actual/rules/cross-cutting-test-environments-define-bd63.md new file mode 100644 index 000000000000..5987c03f791a --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-define-bd63.md @@ -0,0 +1,34 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Test Environments Define + +These rules are ALWAYS ACTIVE for all ASP.NET Core services implementing authorization policies, particularly those exposing SCIM v2 endpoints with policy-based authorization configuration. + +### Rules + +- **R-AUTHZ-001** SHOULD: Test environments SHOULD define separate authorization policies using policy.RequireAssertion() to bypass production authorization requirements + +### Verify + +```bash +# Verify services.AddAuthorization configuration exists +grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify production policy requires api.scim scope claim +grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs + +# Verify authentication is called before authorization in pipeline +grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ + +# Verify controllers reference authorization policies by name +grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ +``` + +**Accept when:** +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration +- Test-specific authorization bypass patterns (RequireAssertion(a => true)) appear only in test application factories, never in production Startup.cs + + +Clause Code MUST NOT skip or defer verification of authorization policy configuration. All SCIM endpoints MUST be protected by named authorization policies registered in Startup.cs. Test environments MUST use isolated authorization configuration that does not leak into production deployments. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-register-a385.md b/.actual/rules/cross-cutting-test-environments-register-a385.md new file mode 100644 index 000000000000..be4d8ea43188 --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-register-a385.md @@ -0,0 +1,29 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Test Environments Register + +These rules are ALWAYS ACTIVE for all test environment service registration code, factory classes, and dependency injection configuration in integration test scenarios. + +### Rules + +- **R-TEST-DI-001** MUST: Test environments MUST register no-op or mock implementations for external service dependencies (e.g., IMailService) to prevent side effects. + +### Verify + +```bash +# Verify dependency injection patterns are actively used +grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l + +# Verify authentication configuration exists +grep -r 'AddAuthentication' --include='*.cs' | head -5 + +# Verify test factory classes exist with service collection configuration +find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; +``` + +**Accept when:** +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + + +Claude Code MUST NOT skip or defer verification. Service registration patterns must be validated through code review and static analysis to ensure test environments properly isolate external dependencies via dependency injection container configuration. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-use-9167.md b/.actual/rules/cross-cutting-test-environments-use-9167.md new file mode 100644 index 000000000000..316d01b866dd --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-use-9167.md @@ -0,0 +1,30 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Test Environments Use + +These rules are ALWAYS ACTIVE for all ASP.NET Core API controllers with authorization enforcement points, controller actions handling organization user management operations, SCIM integration endpoints requiring policy-based authorization, and administrative console controllers managing access control. + +### Rules + +- **R-AUTH-001** MAY: Test environments MAY use custom AuthenticationHandler implementations (e.g., TestAuthHandler) to simulate authentication for integration testing. + +### Verify + +```bash +# Count IAuthorizationService usage in controllers +grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l + +# Count AuthorizeAsync calls in controllers +grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l + +# Count [Authorize] attributes in controllers +grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l +``` + +**Accept when:** +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) +- Test environments use custom AuthenticationHandler implementations for integration testing without bypassing authorization checks in production code + + +Claude Code MUST NOT skip or defer verification of authorization enforcement patterns. All protected controller actions MUST be verified to contain appropriate authorization checks before operations on protected resources. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-use-bc29.md b/.actual/rules/cross-cutting-test-environments-use-bc29.md new file mode 100644 index 000000000000..9bc0a367e390 --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-use-bc29.md @@ -0,0 +1,31 @@ +# Establish HTTP Client Boundaries for External Service Integration: Test Environments Use + +These rules are ALWAYS ACTIVE for all outbound HTTP requests to external services, APIs, and third-party integrations in test environments, including SCIM endpoint integrations, pricing service clients, and identity provider communications. + +### Rules + +- **R-HTTP-001** SHOULD: Test environments SHOULD use custom authentication handlers (e.g., TestAuthHandler) to simulate external authentication without network calls. + +### Verify + +```bash +# Verify no direct HttpClient instantiation outside documented legacy exceptions +grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' + +# Verify SSRF protection handlers are detected +grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' + +# Count IHttpClientFactory injection points +grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' +``` + +**Accept when:** +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services +- All HTTP clients are registered in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- Test projects configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration + + +Claude Code MUST NOT skip or defer verification. All pull requests adding external service integrations must pass code review checklist verification, static analysis for direct HttpClient instantiation patterns, and integration test suite validation that external client boundaries are properly mocked in test environments. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-use-f094.md b/.actual/rules/cross-cutting-test-environments-use-f094.md new file mode 100644 index 000000000000..366ec6244601 --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-use-f094.md @@ -0,0 +1,31 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Test Environments Use + +These rules are ALWAYS ACTIVE for all SCIM service implementations and authorization enforcement points within the domain modeling layer, including startup configuration, middleware pipeline components, and controller authorization attributes. + +### Rules + +- **R-SCIM-AUTH-001** SHOULD: Test environments SHOULD use simplified authorization policies with RequireAssertion for integration testing scenarios. + +### Verify + +```bash +# Verify AddAuthorization configuration with named Scim policy +grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' + +# Verify production policies include api.scim scope requirement +grep -r 'RequireClaim.*api\.scim' --include='*.cs' + +# Verify middleware ordering: UseAuthentication before UseAuthorization +grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' +``` + +**Accept when:** +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods +- Test environments use RequireAssertion(a => true) for simplified authorization in integration test scenarios +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes enforce the named policy + + +Clause Code MUST NOT skip or defer verification of authorization policy configuration in startup classes and middleware pipeline ordering. Authorization enforcement points MUST be established between authentication and controller execution for all SCIM endpoints. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-environments-use-f608.md b/.actual/rules/cross-cutting-test-environments-use-f608.md new file mode 100644 index 000000000000..3ebd68933bb3 --- /dev/null +++ b/.actual/rules/cross-cutting-test-environments-use-f608.md @@ -0,0 +1,45 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Test Environments Use + +These rules are ALWAYS ACTIVE for ASP.NET Core applications using AddAuthorization for policy-based authorization, SCIM API endpoints requiring scope-based access control, services using ApiKeyAuthenticationHandler or custom authentication schemes, and integration test factories requiring authorization policy configuration. + +### Rules + +- **R-AUTH-001** SHOULD: Test environments SHOULD use permissive authorization policies (RequireAssertion) to enable integration testing without external authentication dependencies. +- **R-AUTH-002** MUST: Production Startup.cs files MUST contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim(). +- **R-AUTH-003** MUST: Named policy strings MUST be defined as constants in shared configuration classes and referenced in both policy configuration and controller attributes to ensure compile-time verification. +- **R-AUTH-004** MUST: Authentication schemes MUST be configured using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation. +- **R-AUTH-005** SHOULD: Authorization policy requirements (scope names, claim types) SHOULD be externalized using IOptions or similar configuration objects rather than hardcoded in Startup. +- **R-AUTH-006** MUST: No production configuration files MUST contain authorization policies with RequireAssertion(a => true) or other permissive assertions. +- **R-AUTH-007** SHOULD: Authorization policy requirements SHOULD be documented in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers. +- **R-AUTH-008** SHOULD: Logging SHOULD be implemented in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting. + +### Verify + +```bash +# Verify production code does not use permissive test policies +grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' + +# Confirm production authorization requires authentication and claims +grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' + +# Validate policy definitions include security requirements +grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' + +# Verify test factories use RequireAssertion only in test-specific files +grep -r 'RequireAssertion' --include='*ApplicationFactory.cs' --include='*TestStartup.cs' + +# Ensure no RequireAssertion in production Startup files +grep -r 'RequireAssertion' --include='Startup.cs' && echo 'FAIL: Found RequireAssertion in production Startup' || echo 'PASS: No RequireAssertion in production Startup' +``` + +**Accept when:** +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions +- Policy names are defined as constants in shared configuration classes +- Authentication is configured before authorization policies +- Authorization policy requirements are externalized in configuration objects + + +Claude Code MUST NOT skip or defer verification. All rules MUST be checked before accepting code changes. Security team review is required for any authorization policy changes before merge to main branch. CI/CD pipeline MUST fail builds containing permissive authorization policies in production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-factories-configure-fdb2.md b/.actual/rules/cross-cutting-test-factories-configure-fdb2.md new file mode 100644 index 000000000000..45d6063b8382 --- /dev/null +++ b/.actual/rules/cross-cutting-test-factories-configure-fdb2.md @@ -0,0 +1,35 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Factories Configure + +These rules are ALWAYS ACTIVE for all integration tests in the SCIM test infrastructure, specifically test factories, authentication configuration, and database persistence patterns within the bitwarden_license/test/Scim.IntegrationTest scope. + +### Rules + +- **R-SCIM-001** MUST: Test factories MUST configure authentication using AuthenticationHandler with ClaimsIdentity for organizational context. +- **R-SCIM-002** MUST: Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests. +- **R-SCIM-003** MUST: Use async/await consistently for both SaveChangesAsync() and HTTP client methods (GetAsync, PostAsync, PutAsync, PatchAsync) to maintain proper execution order. +- **R-SCIM-004** SHOULD: Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data. +- **R-SCIM-005** SHOULD: Batch related entity creation and call SaveChanges once per logical setup phase to avoid performance degradation. +- **R-SCIM-006** SHOULD: Inject test doubles (e.g., NoopMailService) in ScimApplicationFactory to prevent external side effects during integration tests. + +### Verify + +```bash +# Verify SaveChanges usage in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Count async HTTP operations +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify authentication configuration in test factories +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- No race conditions exist between database writes and API reads in test execution + + +Claude Code MUST NOT skip or defer verification. All R-SCIM rules must be validated during code review of integration test pull requests and monitored by CI pipeline test execution for flaky tests. Violations require explicit SaveChanges calls or documented exceptions approved by the test infrastructure team lead. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-factories-use-7687.md b/.actual/rules/cross-cutting-test-factories-use-7687.md new file mode 100644 index 000000000000..71595a65bae5 --- /dev/null +++ b/.actual/rules/cross-cutting-test-factories-use-7687.md @@ -0,0 +1,40 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Test Factories Use + +These rules are ALWAYS ACTIVE for all SCIM API integration test files, test factories, and test infrastructure code that handles HTTP request/response serialization and Entity Framework data persistence. + +### Rules + +- **R-SCIM-TF-001** MAY: Test factories MAY use custom AuthenticationHandler implementations for simulating SCIM client authentication. +- **R-SCIM-TF-002** MUST: Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema compliance. +- **R-SCIM-TF-003** MUST: Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers. +- **R-SCIM-TF-004** MUST: Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases. +- **R-SCIM-TF-005** SHOULD: Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior. +- **R-SCIM-TF-006** SHOULD: Use QueryString manipulation for SCIM filter/pagination parameters in GET requests. +- **R-SCIM-TF-007** MUST: All SCIM integration test files import System.Text.Json for serialization. +- **R-SCIM-TF-008** MUST: Data persistence operations use DatabaseContext.SaveChanges pattern. +- **R-SCIM-TF-009** MUST: Test authentication handlers construct ClaimsIdentity using System.Security.Claims. + +### Verify + +```bash +# Verify System.Text.Json usage in SCIM integration tests +grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify DatabaseContext.SaveChanges pattern usage +grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Verify System.Security.Claims usage in test factories +grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims +- JsonSerializerOptions are explicitly configured in test factory with SCIM-appropriate settings +- DatabaseContext is scoped per test to prevent state leakage +- Tests use ScimApplicationFactory pattern for HTTP serialization + + +Claude Code MUST NOT skip or defer verification of these rules. Code review of SCIM integration test changes MUST verify compliance. Static analysis scanning for System.Text.Json usage in test projects MUST be performed. CI pipeline verification that tests use ScimApplicationFactory pattern MUST pass. Pull requests introducing alternative serializers in SCIM tests MUST require architecture review. Tests bypassing DatabaseContext.SaveChanges MUST document rationale in comments. Non-compliant test code MUST be flagged in code review with request for alignment. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixture-setup-79b4.md b/.actual/rules/cross-cutting-test-fixture-setup-79b4.md new file mode 100644 index 000000000000..aa6eff59d21f --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixture-setup-79b4.md @@ -0,0 +1,46 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Test Fixture Setup + +These rules are ALWAYS ACTIVE for all unit tests in Bit.Core.AdminConsole, Bit.Commercial.Core.SecretsManager, and related test projects that verify asynchronous commands, queries, and repository operations using AutoFixture and NSubstitute. + +### Rules + +- **R-ASYNC-TEST-001** MUST: Declare test methods as `public async Task MethodName_Scenario_ExpectedResult()` when testing async system-under-test methods. +- **R-ASYNC-TEST-002** MUST: Use `await` when invoking `sutProvider.Sut` methods that return `Task` or `Task`. +- **R-ASYNC-TEST-003** MUST: Use `await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))` for exception testing in async methods. +- **R-ASYNC-TEST-004** MUST: Call `Received()` verification on mocked dependencies only after awaiting system-under-test invocations. +- **R-ASYNC-TEST-005** SHOULD: Configure AutoFixture and sutProvider in test class constructor or setup method for consistent test fixture initialization. +- **R-ASYNC-TEST-006** SHOULD: Use `Arg.Is` with lambda expressions to validate collection contents and DateTime parameters in mock verification. +- **R-ASYNC-TEST-007** MUST NOT: Use synchronous blocking patterns (`.Result`, `.Wait()`) on Task-returning methods in test code. +- **R-ASYNC-TEST-008** MUST NOT: Declare test methods as `async void`; always use `async Task` for unit tests. +- **R-ASYNC-TEST-009** MUST NOT: Use `Task.Run` to wrap synchronous test code or async method invocations. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count await invocations on sutProvider.Sut +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect synchronous blocking patterns (should return 0) +grep -r '\.Result\|.Wait()' bitwarden_license/test/ --include='*.cs' | grep -v '//' | wc -l + +# Detect async void test methods (should return 0) +grep -r 'public async void.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as `async Task` and use `await`. +- Exception testing for async methods uses `Assert.ThrowsAsync` with `await` rather than synchronous assertions. +- Mock verification with `Received()` occurs after awaiting system-under-test invocations in all test cases. +- No synchronous blocking patterns (`.Result`, `.Wait()`) appear in test code outside of comments. +- No `async void` test methods are present in the codebase. +- AutoFixture and sutProvider are consistently configured in test class constructors or setup methods. + + +Claude Code MUST NOT skip or defer verification. All async test methods MUST be reviewed for proper await usage, exception handling patterns, and mock verification ordering before accepting pull requests. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixtures-cryptographic-562a.md b/.actual/rules/cross-cutting-test-fixtures-cryptographic-562a.md new file mode 100644 index 000000000000..8e26a8567de5 --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixtures-cryptographic-562a.md @@ -0,0 +1,29 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Test Fixtures Cryptographic + +These rules are ALWAYS ACTIVE for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings, including build scripts (build.rs), test fixtures, and cryptographic operation testing code. + +### Rules + +- **R-FFI-001** MUST: Test fixtures for cryptographic operations MUST use clearly labeled fake key material (e.g., _FAKE_RSA_KEY_*) to prevent accidental use in production. + +### Verify + +```bash +# Verify csbindgen is configured in build.rs +grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs + +# Count fake RSA key constants +grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' + +# Verify generated bindings exist +test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' +``` + +**Accept when:** +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + + +Claude Code MUST NOT skip or defer verification. Violations are caught by automated CI checks that verify build.rs successfully generates C# bindings, code review processes that check csbindgen configuration and test fixture naming conventions, and static analysis tools that scan for test constant usage in production code paths. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixtures-requiring-be91.md b/.actual/rules/cross-cutting-test-fixtures-requiring-be91.md new file mode 100644 index 000000000000..8824efd07502 --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixtures-requiring-be91.md @@ -0,0 +1,36 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Fixtures Requiring + +These rules are ALWAYS ACTIVE for all test code requiring cryptographic key fixtures in the Rust SDK. + +### Rules + +- **R-CRYPTO-001** SHOULD: Test fixtures requiring multiple distinct key pairs SHOULD use numbered sequences (_FAKE_RSA_KEY_0, _FAKE_RSA_KEY_1, etc.) to provide clear identification. +- **R-CRYPTO-002** MUST: All fake RSA key constants MUST be defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks to ensure test-only compilation. +- **R-CRYPTO-003** MUST: Fake key constants MUST contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries. +- **R-CRYPTO-004** MUST: No references to `_FAKE_RSA_KEY_` constants MUST appear in production code paths outside test modules. +- **R-CRYPTO-005** SHOULD: Fake keys SHOULD be defined with descriptive names following the pattern `const _FAKE_RSA_KEY_N: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----";` +- **R-CRYPTO-006** SHOULD: Module-level comments SHOULD document the key generation parameters (algorithm, key size, format) for future maintenance. + +### Verify + +```bash +# Check for production usage of fake RSA keys outside test modules +grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' + +# Count embedded private key blocks in rsa_keys module +grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l + +# Verify test execution +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' +``` + +**Accept when:** +- All fake RSA key constants are defined in test-only modules with `#[cfg(test)]` or within `mod tests` blocks +- At least 5 distinct fake RSA key constants are available in `util/RustSdk/rust/src/rsa_keys.rs` with sequential numbering +- No references to `_FAKE_RSA_KEY_` constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries +- Module-level comments document key generation parameters (algorithm, key size, format) + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for test fixture code in scope. Violations MUST be caught during code review and CI pipeline checks before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-fixtures-use-2eaa.md b/.actual/rules/cross-cutting-test-fixtures-use-2eaa.md new file mode 100644 index 000000000000..e200482e78fc --- /dev/null +++ b/.actual/rules/cross-cutting-test-fixtures-use-2eaa.md @@ -0,0 +1,39 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Test Fixtures Use + +These rules are ALWAYS ACTIVE for all public extern "C" functions in util/RustSdk/rust/src/ that accept c_char pointer parameters, and for FFI helper functions that process C string inputs before cryptographic operations. + +### Rules + +- **R-FFI-001** MUST: Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers. +- **R-FFI-002** MUST: Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking. +- **R-FFI-003** MUST: For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks. +- **R-FFI-004** SHOULD: Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior. +- **R-FFI-005** SHOULD: Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files. +- **R-FFI-006** MAY: Test fixtures MAY use hardcoded string constants (_FAKE_RSA_KEY_*) to validate FFI string handling without requiring external C callers. + +### Verify + +```bash +# Verify all extern "C" functions accepting c_char pointers use CStr::from_ptr +grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' + +# Verify count of CString::into_raw matches string-returning FFI functions +grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l + +# Run FFI-specific tests including invalid input cases +cargo test --package rust-sdk -- ffi + +# Run clippy lints for unsafe FFI patterns +cargo clippy --package rust-sdk -- -W clippy::missing_safety_doc -W clippy::not_unsafe_ptr_arg_deref +``` + +**Accept when:** +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling +- Clippy lints pass without warnings for unsafe FFI patterns +- All FFI function comments document string encoding requirements and memory ownership semantics + + +Claude Code MUST NOT skip or defer verification. All verify commands MUST execute successfully before accepting FFI code changes. CI build MUST fail if grep verification detects extern "C" functions missing CStr conversion. Code review MUST reject FFI changes lacking null checks, UTF-8 validation, or error handling. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-helpers-report-03d0.md b/.actual/rules/cross-cutting-test-helpers-report-03d0.md new file mode 100644 index 000000000000..00232ffe249e --- /dev/null +++ b/.actual/rules/cross-cutting-test-helpers-report-03d0.md @@ -0,0 +1,30 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Test Helpers Report + +These rules are ALWAYS ACTIVE for all API controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes and their corresponding unit test projects using Xunit framework. + +### Rules + +- **R-AUTH-001** SHOULD: Test helpers SHOULD report all missing authorization attributes in a single test failure rather than failing on the first violation. + +### Verify + +```bash +# Count invocations of authorization test helper across test projects +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run authorization-specific unit tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes applied to controller classes +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- Test failures report all missing authorization attributes in a single failure message rather than stopping at the first violation + + +Claude Code MUST NOT skip or defer verification of authorization attribute presence on API controller HTTP methods. All public HTTP action methods (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST be validated for authorization attributes via unit test helpers before code review approval. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-methods-that-9dfa.md b/.actual/rules/cross-cutting-test-methods-that-9dfa.md new file mode 100644 index 000000000000..b90badb915d8 --- /dev/null +++ b/.actual/rules/cross-cutting-test-methods-that-9dfa.md @@ -0,0 +1,38 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Test Methods That + +These rules are ALWAYS ACTIVE for all unit test files in Bit.Core.AdminConsole, Bit.Commercial.Core.SecretsManager, and related test projects that invoke asynchronous system-under-test methods. + +### Rules + +- **R-ASYNC-TEST-001** MUST: Test methods that invoke asynchronous system-under-test methods MUST be declared as async and use await when calling methods returning Task or Task. +- **R-ASYNC-TEST-002** MUST: Exception testing for async methods MUST use Assert.ThrowsAsync with await rather than synchronous assertions. +- **R-ASYNC-TEST-003** MUST: Mock verification with Received() MUST occur after awaiting system-under-test invocations in all test cases. +- **R-ASYNC-TEST-004** MUST: Test methods MUST NOT use synchronous blocking patterns (.Result, .Wait()) on Task-returning methods. +- **R-ASYNC-TEST-005** MUST: Compiler warnings for unawaited tasks in test projects MUST be treated as errors. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count await usage with sutProvider.Sut +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect blocking patterns in test files +grep -r '\.Result\|.Wait()' bitwarden_license/test/ --include='*.cs' | grep -v 'TODO\|FIXME' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases +- No synchronous blocking patterns (.Result, .Wait()) are found on Task-returning methods in test code +- Compiler warnings for unawaited tasks are configured as errors in test project settings + + +Claude Code MUST NOT skip or defer verification. All async test methods MUST be verified to use await patterns and MUST NOT use blocking calls. Pull requests with violations MUST be rejected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-servers-inject-716f.md b/.actual/rules/cross-cutting-test-servers-inject-716f.md new file mode 100644 index 000000000000..ca3908b929a9 --- /dev/null +++ b/.actual/rules/cross-cutting-test-servers-inject-716f.md @@ -0,0 +1,38 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Servers Inject + +These rules are ALWAYS ACTIVE for all integration tests in the SCIM test infrastructure, specifically files in `bitwarden_license/test/Scim.IntegrationTest/` that use DatabaseContext and HTTP client operations against SCIM v2 endpoints. + +### Rules + +- **R-SCIM-001** MUST: Call `DatabaseContext.SaveChanges()` or `SaveChangesAsync()` after all test entities are created but before executing HTTP requests (GetAsync, PostAsync, PutAsync, PatchAsync). +- **R-SCIM-002** SHOULD: Test servers SHOULD inject NoopMailService or equivalent test doubles for external service dependencies to prevent external side effects during integration tests. +- **R-SCIM-003** MUST: Use async/await consistently for both `SaveChangesAsync()` and HTTP client methods to maintain proper execution order and avoid race conditions. +- **R-SCIM-004** MUST: Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data being validated. +- **R-SCIM-005** SHOULD: Batch related entity creation and call SaveChanges once per logical setup phase to avoid performance degradation from excessive persistence calls. + +### Verify + +```bash +# Verify SaveChanges usage in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Count async HTTP operations +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify test authentication configuration +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +# Verify NoopMailService injection in factory +grep -r 'NoopMailService' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges or SaveChangesAsync before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- NoopMailService or equivalent test doubles are injected in ScimApplicationFactory +- No external service calls occur during test execution + + +Claude Code MUST NOT skip or defer verification. All R-SCIM rules must be checked during code review of integration test pull requests. Violations must be addressed with explicit SaveChanges calls and proper test double injection before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-suites-include-f3f0.md b/.actual/rules/cross-cutting-test-suites-include-f3f0.md new file mode 100644 index 000000000000..6832e311fd90 --- /dev/null +++ b/.actual/rules/cross-cutting-test-suites-include-f3f0.md @@ -0,0 +1,36 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Test Suites Include + +These rules are ALWAYS ACTIVE for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers, including all public FFI functions in util/RustSdk/rust/src/lib.rs, modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs, functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations, and memory management functions like free_c_string. + +### Rules + +- **R-FFI-001** SHOULD: Test suites SHOULD include fake key fixtures (e.g., _FAKE_RSA_KEY_N constants) to validate input handling without requiring real cryptographic material. +- **R-FFI-002** MUST: Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation before dereferencing. +- **R-FFI-003** MUST: Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string. +- **R-FFI-004** MUST: Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers. +- **R-FFI-005** MUST: Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called. +- **R-FFI-006** MAY: Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds. + +### Verify + +```bash +# Check that all public FFI functions accepting c_char pointers include CStr validation +grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' + +# Verify at least 5 fake RSA key fixtures exist +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' + +# Confirm RSA key validation tests pass +cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' +``` + +**Accept when:** +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs +- All outbound FFI strings use CString::new().into_raw() with documented ownership semantics +- Memory management functions like free_c_string are properly tracked and documented + + +Claude Code MUST NOT skip or defer verification. CI pipeline MUST run grep-based checks for CStr usage patterns in FFI functions. Code review checklist MUST require security team sign-off on new FFI functions. Cargo test suite MUST include negative test cases with malformed input. CI build MUST fail if FFI functions lack CStr validation patterns. Security team MUST block PR merge until validation is added and tested. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-test-suites-requiring-a086.md b/.actual/rules/cross-cutting-test-suites-requiring-a086.md new file mode 100644 index 000000000000..d20686d4ef2d --- /dev/null +++ b/.actual/rules/cross-cutting-test-suites-requiring-a086.md @@ -0,0 +1,40 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Test Suites Requiring + +These rules are ALWAYS ACTIVE for all test code that exercises cryptographic operations in public API protocols, including unit tests, integration tests, protocol validation tests, and build-time test execution in the Rust SDK module and C# interop test suites. + +### Rules + +- **R-FAKE-RSA-001** SHOULD: Test suites requiring multiple key pairs for protocol validation SHOULD provide at least 5 distinct fake RSA keys to support key rotation, multi-party, and edge case scenarios. +- **R-FAKE-RSA-002** MUST: All fake RSA keys MUST be embedded as const string literals in test fixtures and marked with the _FAKE_RSA_KEY_N naming convention (zero-indexed sequential numbering). +- **R-FAKE-RSA-003** MUST: Fake RSA key constants MUST never appear in production source files outside of test modules; static analysis MUST verify this constraint. +- **R-FAKE-RSA-004** MUST: Each fake RSA key block MUST include a comment header explicitly stating it is a test fixture and must never be used in production. +- **R-FAKE-RSA-005** SHOULD: C# test code consuming the Rust SDK via csbindgen SHOULD reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys. +- **R-FAKE-RSA-006** MAY: Performance benchmarking tests MAY use real key generation timing measurements as an exception to the embedded fake key requirement (EXC-001). + +### Verify + +```bash +# Verify no fake keys appear in production code +grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' + +# Verify RSA key tests pass +cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' + +# Verify at least 5 distinct fake RSA keys exist +grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +# Verify naming convention compliance +grep '_FAKE_RSA_KEY_[0-9]' util/RustSdk/rust/src/rsa_keys.rs | wc -l | awk '$1 >= 5 {print "Naming convention verified"}' +``` + +**Accept when:** +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys +- C# interop tests can successfully use the same key material as Rust tests +- Each fake RSA key constant includes a comment header stating it is for testing only +- Static analysis confirms _FAKE_RSA_KEY_ patterns do not appear in non-test files + + +Claude Code MUST NOT skip or defer verification. CI pipeline static analysis checks MUST fail if fake key patterns appear in production code paths. Code review MUST block merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow the naming convention. Security team notification MUST be triggered for any violation detected in production branches. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-append-custom-9f5d.md b/.actual/rules/cross-cutting-tests-append-custom-9f5d.md new file mode 100644 index 000000000000..785a75d0d872 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-append-custom-9f5d.md @@ -0,0 +1,36 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Tests Append Custom + +These rules are ALWAYS ACTIVE for all integration tests in the SCIM test infrastructure, specifically files in `bitwarden_license/test/Scim.IntegrationTest/` that interact with DatabaseContext and HTTP client operations. + +### Rules + +- **R-SCIM-001** MUST: Call `DatabaseContext.SaveChanges()` or `SaveChangesAsync()` after all test entities are created but before executing HTTP requests (GetAsync, PostAsync, PutAsync, PatchAsync). +- **R-SCIM-002** MUST: Use async/await consistently for both `SaveChangesAsync()` and HTTP client methods to maintain proper execution order and avoid race conditions. +- **R-SCIM-003** MUST: Configure test authentication via `TestAuthHandler` with appropriate claims (e.g., orgadmin) matching the organizational context of test data. +- **R-SCIM-004** MAY: Tests MAY append custom headers (e.g., UserAgent) to HTTP requests to simulate specific client behaviors. +- **R-SCIM-005** SHOULD: Batch related entity creation and call SaveChanges once per logical setup phase to avoid performance degradation. +- **R-SCIM-006** SHOULD: Inject test doubles (e.g., NoopMailService) in ScimApplicationFactory to prevent external side effects during integration tests. + +### Verify + +```bash +# Verify SaveChanges usage in integration tests +grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ + +# Count async HTTP operations +grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l + +# Verify test authentication configuration +grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ +``` + +**Accept when:** +- All integration tests in Scim.IntegrationTest call SaveChanges (or SaveChangesAsync) before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination +- Custom headers are appended only where necessary to simulate specific client behaviors +- Test doubles are injected in ScimApplicationFactory to prevent external side effects + + +Claude Code MUST NOT skip or defer verification. All R-SCIM rules must be validated during code review of integration test pull requests. Violations must be addressed with explicit SaveChanges calls or documented exceptions approved by the test infrastructure team lead. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-assert-jsonvaluekind-54d7.md b/.actual/rules/cross-cutting-tests-assert-jsonvaluekind-54d7.md new file mode 100644 index 000000000000..f47d0cd7ab6f --- /dev/null +++ b/.actual/rules/cross-cutting-tests-assert-jsonvaluekind-54d7.md @@ -0,0 +1,33 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Assert Jsonvaluekind + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses using System.Text.Json. + +### Rules + +- **R-OAUTH-001** MUST: Tests MUST assert JsonValueKind.Object for complex response properties before extracting nested values. + +### Verify + +```bash +# Check for System.Text.Json usage in integration tests +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Check for explicit error message validation +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run OAuth token endpoint integration tests +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + + +Clause Code MUST NOT skip or defer verification. All integration tests asserting on OAuth token endpoint JSON responses MUST follow the JsonValueKind.Object assertion pattern before property extraction. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-cover-both-d730.md b/.actual/rules/cross-cutting-tests-cover-both-d730.md new file mode 100644 index 000000000000..9f09727f5437 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-cover-both-d730.md @@ -0,0 +1,44 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Cover Both + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.Test suite that exercise query classes in the SecretsManager domain, particularly those coordinating access policy updates and secret synchronization operations. + +### Rules + +- **R-ISUT-001** SHOULD: Tests SHOULD cover both empty state scenarios (NoCurrentGrantedPolicies, NoCurrentAccessPolicies) and change detection scenarios (CurrentGrantedPolicies, CurrentAccessPolicies) to validate conditional branching in query coordination logic. + +- **R-ISUT-002** MUST: Query unit tests MUST use the sutProvider pattern to inject mock repository dependencies (ISecretRepository, IServiceAccountRepository) rather than instantiating concrete implementations. + +- **R-ISUT-003** MUST: Tests MUST access the system under test only through its public interface (e.g., sutProvider.Sut.GetAsync) and MUST NOT directly instantiate repository implementations or establish database connections. + +- **R-ISUT-004** SHOULD: Test assertions SHOULD prioritize verification of query result correctness (operation classification, counts, data integrity) over exhaustive mock call verification. + +- **R-ISUT-005** SHOULD: Test methods SHOULD follow Arrange-Act-Assert pattern with descriptive naming that indicates scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates). + +- **R-ISUT-006** MUST: Query unit tests MUST NOT require database connections, external service dependencies, or in-memory database implementations during execution. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations in query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Count operation classification assertions +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit tests without database configuration +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +# Detect direct repository instantiation in test code +grep -r 'new.*Repository' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | grep -v 'Mock\|Substitute' || echo 'No direct instantiations found' +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- No direct repository instantiation patterns are detected in test code (only mocks/substitutes) +- Test execution completes within performance thresholds (individual tests <100ms) + + +Clause Code MUST NOT skip or defer verification of these rules. Pull requests introducing query tests with database dependencies MUST be rejected. CI pipeline failures on unit test suite MUST block merge. Tests exceeding execution time thresholds MUST be flagged for review of external dependencies. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-asserthelper-e296.md b/.actual/rules/cross-cutting-tests-use-asserthelper-e296.md new file mode 100644 index 000000000000..ac3f523354ba --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-asserthelper-e296.md @@ -0,0 +1,41 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Use Asserthelper + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses, including password grant, SSO authorization code flow, and trusted device encryption scenarios. + +### Rules + +- **R-OAUTH-JSON-001** MUST: Use System.Text.Json for parsing HTTP response content in OAuth token endpoint integration tests. +- **R-OAUTH-JSON-002** MUST: Validate JsonValueKind.Object before accessing properties on complex JSON response objects. +- **R-OAUTH-JSON-003** MUST: Use Assert.Equal with explicit expected error message strings when validating authentication failure responses (e.g., 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device'). +- **R-OAUTH-JSON-004** SHOULD: Use AssertHelper.AssertResponseTypeIs for type-safe response validation in OAuth token endpoint tests. +- **R-OAUTH-JSON-005** MUST: Validate userDecryptionOptions object presence and structure in addition to standard token response properties for SSO and trusted device encryption flows. +- **R-OAUTH-JSON-006** MUST: Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information). +- **R-OAUTH-JSON-007** SHOULD: Extract and assert on nested JSON values using GetProperty() methods after validating parent object structure. + +### Verify + +```bash +# Count System.Text.Json usage in integration tests +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Check for explicit error message assertions +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run OAuth token endpoint integration tests +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place +- userDecryptionOptions object presence and structure are validated in SSO and trusted device encryption flow tests +- Token requests are constructed using FormUrlEncodedContent with all required OAuth parameters + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for OAuth token endpoint integration tests. Code review must confirm System.Text.Json usage and JsonValueKind assertions before merge. CI pipeline execution of Identity.IntegrationTest suite must pass. Violations block merge until corrected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-async-e659.md b/.actual/rules/cross-cutting-tests-use-async-e659.md new file mode 100644 index 000000000000..3727cba264c9 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-async-e659.md @@ -0,0 +1,31 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Use Async + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.Test suite that test query classes in the SecretsManager domain, particularly those coordinating access policy updates and secret synchronization operations. + +### Rules + +- **R-ASYNC-001** MUST: Tests MUST use async/await patterns when invoking query methods that return Task types to properly test asynchronous coordination logic. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations across query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Verify operation classification assertions are present +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Run query unit tests to confirm no database dependencies +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- Test methods follow Arrange-Act-Assert pattern with async/await for Task-returning query methods +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm external boundary interactions without concrete implementations + + +Claude Code MUST NOT skip or defer verification of async/await usage in query test invocations. Code review and CI pipeline execution are mandatory before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-dependency-eab0.md b/.actual/rules/cross-cutting-tests-use-dependency-eab0.md new file mode 100644 index 000000000000..91086e019543 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-dependency-eab0.md @@ -0,0 +1,39 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Use Dependency + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.SecretsManager.Queries namespace and related query test classes that coordinate access policy updates and secret synchronization operations. + +### Rules + +- **R-QUERY-001** MUST: Tests MUST use dependency injection providers (sutProvider) to supply mock implementations of repository interfaces (ISecretRepository, IServiceAccountRepository) to the system under test. +- **R-QUERY-002** MUST: Query test classes MUST access the system under test only through its public interface (e.g., sutProvider.Sut.GetAsync) rather than direct instantiation or internal method invocation. +- **R-QUERY-003** MUST: Test assertions MUST verify operation classification (AccessPolicyOperation enum values: Create/Update/Delete) and query result correctness rather than exhaustive mock call verification. +- **R-QUERY-004** SHOULD: Test methods SHOULD follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties. +- **R-QUERY-005** SHOULD: Test method names SHOULD descriptively indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates). +- **R-QUERY-006** MAY: Critical repository interactions MAY be verified using Received() assertions, but result correctness MUST be prioritized over exhaustive call verification. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations in query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Count operation classification assertions +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit test suite +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +# Detect direct repository instantiation in test code +grep -r 'new.*Repository' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | grep -v 'Substitute.For' | wc -l +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- No direct repository instantiation detected in test code (only dependency injection via sutProvider) +- Test execution time per test remains under 100ms threshold + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for query test classes. Code review and CI pipeline execution must confirm compliance before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-linq-ad5d.md b/.actual/rules/cross-cutting-tests-use-linq-ad5d.md new file mode 100644 index 000000000000..fde4909c1f5e --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-linq-ad5d.md @@ -0,0 +1,45 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Use Linq + +These rules are ALWAYS ACTIVE for all unit tests in Bit.Core.AdminConsole and Bit.Commercial.Core.SecretsManager that invoke asynchronous system-under-test methods and verify their behavior. + +### Rules + +- **R-ASYNC-001** MUST: Declare test methods as `public async Task MethodName_Scenario_ExpectedResult()` when testing async system-under-test methods. +- **R-ASYNC-002** MUST: Use `await` when invoking system-under-test methods that return `Task` or `Task`. +- **R-ASYNC-003** MUST: Use `await Assert.ThrowsAsync()` for exception testing of async methods rather than synchronous assertions. +- **R-ASYNC-004** MUST: Call `Received()` verification on mocked dependencies only after awaiting system-under-test invocations. +- **R-ASYNC-005** MAY: Use LINQ `Select` with `ToArray`/`ToList` to construct test data collections for member operations. +- **R-ASYNC-006** MUST NOT: Use synchronous blocking patterns (`.Result`, `.Wait()`) on `Task`-returning methods in tests. +- **R-ASYNC-007** MUST NOT: Use `async void` test methods; always use `async Task`. +- **R-ASYNC-008** MUST NOT: Use `Task.Run` to wrap synchronous test code or execute async methods. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count await invocations on sutProvider.Sut +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect blocking patterns (should return 0) +grep -r '\.Result\|.Wait()' bitwarden_license/test/ --include='*.cs' | grep -v '//' | wc -l + +# Detect async void test methods (should return 0) +grep -r 'public async void.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as `async Task` and use `await`. +- Exception testing for async methods uses `Assert.ThrowsAsync` with `await` rather than synchronous assertions. +- Mock verification with `Received()` occurs after awaiting system-under-test invocations in all test cases. +- No synchronous blocking patterns (`.Result`, `.Wait()`) appear in test code. +- No `async void` test methods are present in the codebase. +- LINQ `Select` with `ToArray`/`ToList` is used for constructing test data collections where appropriate. + + +Claude Code MUST NOT skip or defer verification. All async test methods MUST follow the declared patterns. Violations of R-ASYNC-002, R-ASYNC-003, R-ASYNC-004, R-ASYNC-006, and R-ASYNC-007 are blocking and must be corrected before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-use-received-b50c.md b/.actual/rules/cross-cutting-tests-use-received-b50c.md new file mode 100644 index 000000000000..ba500df7c23f --- /dev/null +++ b/.actual/rules/cross-cutting-tests-use-received-b50c.md @@ -0,0 +1,38 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Use Received + +These rules are ALWAYS ACTIVE for all unit tests in Bit.Core.AdminConsole and Bit.Commercial.Core.SecretsManager that invoke asynchronous system-under-test methods using async/await patterns with AutoFixture and NSubstitute mocking. + +### Rules + +- **R-ASYNC-001** MUST: Tests MUST use Received() verification on mocked dependencies after awaiting the system-under-test invocation to ensure call order verification. +- **R-ASYNC-002** MUST: Test methods invoking async system-under-test methods MUST be declared as `public async Task MethodName_Scenario_ExpectedResult()`. +- **R-ASYNC-003** MUST: Exception testing for async methods MUST use `Assert.ThrowsAsync()` with await rather than synchronous assertions. +- **R-ASYNC-004** MUST: All Task-returning calls in test methods MUST be awaited; unawaited tasks are compiler errors. +- **R-ASYNC-005** SHOULD: Structure tests with clear arrange-act-assert phases and use descriptive test names for async operation boundaries. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count awaited sutProvider.Sut invocations +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect unawaited Task-returning calls (should return 0) +grep -r 'sutProvider\.Sut\.[^;]*Task' bitwarden_license/test/ --include='*.cs' | grep -v 'await' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases +- No unawaited Task-returning calls exist in test methods +- Compiler warnings for unawaited tasks are treated as errors in test projects + + +Claude Code MUST NOT skip or defer verification. All async test methods MUST follow the async/await pattern with Received() verification after await. Violations (synchronous blocking with .Result or .Wait(), missing await keywords, or Received() called before await) MUST be rejected in code review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-validate-operation-8bf3.md b/.actual/rules/cross-cutting-tests-validate-operation-8bf3.md new file mode 100644 index 000000000000..6fcc1669871e --- /dev/null +++ b/.actual/rules/cross-cutting-tests-validate-operation-8bf3.md @@ -0,0 +1,40 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Validate Operation + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.SecretsManager.Queries namespace and related query test classes that coordinate access policy updates and secret synchronization operations. + +### Rules + +- **R-QUERY-001** MUST: Tests MUST validate operation classification (AccessPolicyOperation.Create, Update, Delete) in query results to ensure correct coordination logic. +- **R-QUERY-002** MUST: Tests MUST use sutProvider pattern to inject mock repository dependencies into query constructors, accessing the system under test only through its public interface. +- **R-QUERY-003** MUST: Tests MUST NOT instantiate concrete repository implementations or establish database connections in unit test code. +- **R-QUERY-004** SHOULD: Test methods SHOULD follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties. +- **R-QUERY-005** SHOULD: Test methods SHOULD be named descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates). +- **R-QUERY-006** SHOULD: Assertions SHOULD prioritize query result correctness (operation types, counts, data integrity) over exhaustive mock call verification. +- **R-QUERY-007** MAY: Mock verification using Received() assertions MAY be used to verify critical repository interactions, but MUST NOT become the primary focus of test assertions. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations in query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Count operation classification assertions in query tests +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit test suite without database configuration +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +# Detect direct repository instantiation in test code (should return no results) +grep -r 'new.*Repository' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | grep -v 'Mock\|Substitute' || echo 'No direct instantiations found' +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- Test execution time per test does not exceed 100ms, indicating no external dependencies +- No direct repository instantiation patterns are found in test code + + +Clause Code MUST NOT skip or defer verification of these rules. Pull requests introducing query tests with database dependencies MUST be rejected. CI pipeline failures on unit test suite MUST block merge. Tests exceeding 100ms execution time MUST be flagged for review. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-validating-successful-1a26.md b/.actual/rules/cross-cutting-tests-validating-successful-1a26.md new file mode 100644 index 000000000000..d4d305b838a6 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-validating-successful-1a26.md @@ -0,0 +1,40 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Validating Successful + +These rules are ALWAYS ACTIVE for all integration tests in the Identity.IntegrationTest project that validate OAuth /connect/token endpoint responses, including password grant, authorization code, SSO, and trusted device encryption authentication flows. + +### Rules + +- **R-JSON-001** MUST: Use System.Text.Json for parsing HTTP response content in OAuth token endpoint integration tests. +- **R-JSON-002** MUST: Validate JsonValueKind.Object before accessing properties on complex JSON response objects. +- **R-JSON-003** SHOULD: Assert on critical security properties including KDF type, KDF iterations, and encrypted key material in tests validating successful authentication. +- **R-JSON-004** SHOULD: Use Assert.Equal with explicit expected error message strings when validating authentication failure scenarios (e.g., 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device'). +- **R-JSON-005** SHOULD: Validate userDecryptionOptions object presence and structure in addition to standard token response properties for SSO and trusted device encryption flows. +- **R-JSON-006** MUST: Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information). + +### Verify + +```bash +# Check for System.Text.Json usage in integration test files +grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l + +# Verify JsonValueKind.Object assertions are present +grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' + +# Check for explicit error message assertions +grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' + +# Run OAuth token endpoint integration tests +dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build +``` + +**Accept when:** +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place +- Tests validating successful authentication include assertions on KDF type, KDF iterations, and encrypted key material +- userDecryptionOptions object structure is validated in SSO and trusted device encryption test scenarios + + +Claude Code MUST NOT skip or defer verification of these rules during code review of integration test pull requests. Violations block merge until corrected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-asynchronous-557f.md b/.actual/rules/cross-cutting-tests-verify-asynchronous-557f.md new file mode 100644 index 000000000000..e8b9903042be --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-asynchronous-557f.md @@ -0,0 +1,45 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Verify Asynchronous + +These rules are ALWAYS ACTIVE for all unit tests in Bit.Core.AdminConsole and Bit.Commercial.Core.SecretsManager that interact with asynchronous repository and command operations. + +### Rules + +- **R-ASYNC-001** SHOULD: Tests SHOULD verify asynchronous repository operations with Arg.Is matchers to validate complex collection arguments and DateTime parameters. +- **R-ASYNC-002** MUST: Test methods invoking async system-under-test methods MUST be declared as `public async Task MethodName_Scenario_ExpectedResult()`. +- **R-ASYNC-003** MUST: All invocations of async system-under-test methods MUST be awaited using the `await` keyword. +- **R-ASYNC-004** MUST: Exception testing for async methods MUST use `Assert.ThrowsAsync()` with `await` rather than synchronous assertions. +- **R-ASYNC-005** MUST: Mock verification with `Received()` MUST occur after awaiting system-under-test invocations to ensure correct call order validation. +- **R-ASYNC-006** MUST: Compiler warnings for unawaited tasks in test projects MUST be treated as errors. +- **R-ASYNC-007** MUST NOT: Synchronous blocking patterns (`.Result`, `.Wait()`) on Task-returning methods MUST NOT be used in test code. +- **R-ASYNC-008** MUST NOT: Async void test methods MUST NOT be used; only `async Task` is permitted for unit tests. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count await invocations on sutProvider.Sut +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect blocking patterns (should return 0) +grep -r '\.Result\|.Wait()' bitwarden_license/test/ --include='*.cs' | grep -v 'comment\|//' | wc -l + +# Detect async void test methods (should return 0) +grep -r 'public async void.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as `async Task` and use `await` +- Exception testing for async methods uses `Assert.ThrowsAsync` with `await` rather than synchronous assertions +- Mock verification with `Received()` occurs after awaiting system-under-test invocations in all test cases +- No synchronous blocking patterns (`.Result`, `.Wait()`) appear in test code +- No `async void` test methods are present in the codebase +- Compiler warnings for unawaited tasks are configured as errors in test projects + + +Claude Code MUST NOT skip or defer verification. Pull requests with synchronous blocking patterns or missing await keywords in tests MUST be rejected. All async test methods MUST follow the declared pattern. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-number-61b8.md b/.actual/rules/cross-cutting-tests-verify-number-61b8.md new file mode 100644 index 000000000000..13a2cbf10beb --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-number-61b8.md @@ -0,0 +1,31 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Tests Verify Number + +These rules are ALWAYS ACTIVE for unit tests in services and commands that include ILogger dependencies, particularly in error conditions, edge cases, and exceptional flows where logging is expected. + +### Rules + +- **R-LOG-001** MAY: Tests MAY verify the number of times a logger method was called using Received(n) syntax when call frequency is significant to the operational contract. + +### Verify + +```bash +# Count test files using GetDependency>() pattern +grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts +- Logger verification is focused on error paths, security events, and operational alerts where log messages are part of the observable contract +- Test comments document when logger verification is intentionally omitted for purely diagnostic logging + + +Clause EX-001 applies: logging behavior that is purely diagnostic and not part of any operational contract or alerting logic may be exempted from verification. Code review and team lead approval required for exceptions. Claude Code MUST NOT skip verification for error conditions, security events, or operational alerts. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-query-eeeb.md b/.actual/rules/cross-cutting-tests-verify-query-eeeb.md new file mode 100644 index 000000000000..6dcca39db2fc --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-query-eeeb.md @@ -0,0 +1,40 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Verify Query + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.SecretsManager.Queries namespace that verify query coordination behavior through interface-based isolation. + +### Rules + +- **R-QUERY-001** MUST: Tests MUST verify query coordination behavior by asserting on returned data structures (result.ProjectGrantedPolicyUpdates, result.ServiceAccountAccessPolicyUpdates) rather than mocking internal method calls. +- **R-QUERY-002** MUST: Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors. +- **R-QUERY-003** MUST: Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties. +- **R-QUERY-004** SHOULD: Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates). +- **R-QUERY-005** SHOULD: Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification. +- **R-QUERY-006** SHOULD: Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites. +- **R-QUERY-007** MUST: Query unit tests MUST NOT require database connections or external service dependencies. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations in query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Count operation classification assertions +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit test suite without database configuration +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +# Detect direct repository instantiation in test code +grep -r 'new.*Repository' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | grep -v 'Mock\|Substitute' || echo 'No direct instantiation found' +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- No direct repository instantiation appears in test code (only mocks/substitutes via dependency injection) +- Test execution time per test remains under 100ms threshold + + +Claude Code MUST NOT skip or defer verification. All R-QUERY rules are mandatory for query test classes in the SecretsManager domain. Code review and CI pipeline execution must confirm compliance before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-specific-0346.md b/.actual/rules/cross-cutting-tests-verify-specific-0346.md new file mode 100644 index 000000000000..6bcd035d9c9c --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-specific-0346.md @@ -0,0 +1,36 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Tests Verify Specific + +These rules are ALWAYS ACTIVE for unit tests in services and commands that include ILogger dependencies, particularly in test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected. + +### Rules + +- **R-LOG-001** SHOULD: Tests SHOULD verify the specific log level (LogWarning, LogError, etc.) and message content when the exact message is part of the observable contract. +- **R-LOG-002** SHOULD: Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure. +- **R-LOG-003** SHOULD: Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.). +- **R-LOG-004** SHOULD: Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract. +- **R-LOG-005** SHOULD: Document in test comments when logger verification is intentionally omitted for purely diagnostic logging. +- **R-LOG-006** MAY: Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns. + +### Verify + +```bash +# Count existing logger dependency retrievals in tests +grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts +- Error paths and operational events include corresponding logger verification assertions +- Test comments document intentional omissions of logger verification for purely diagnostic logging + + +Claude Code MUST NOT skip or defer verification of logger invocations in unit tests for observability components. Code review checks, CI pipeline execution, and static analysis must confirm that logging behavior is tested alongside business logic for error conditions and operational events. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verify-that-de1c.md b/.actual/rules/cross-cutting-tests-verify-that-de1c.md new file mode 100644 index 000000000000..d89cb5af7f57 --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verify-that-de1c.md @@ -0,0 +1,31 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Verify That + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.SecretsManager.Queries namespace that verify query classes coordinating access policy updates and secret synchronization operations. + +### Rules + +- **R-QUERY-001** SHOULD: Tests SHOULD verify that repository methods were called with expected parameters using mock verification (Received, DidNotReceiveWithAnyArgs) to confirm external boundary interactions. + +### Verify + +```bash +# Verify sutProvider pattern usage in query tests +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Verify operation classification assertions +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Run query unit tests without database dependencies +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) are used to validate external boundary interactions +- Test methods follow Arrange-Act-Assert pattern with descriptive naming + + +Claude Code MUST NOT skip or defer verification. Code review MUST confirm new query test classes follow sutProvider pattern and mock repository dependencies. CI pipeline execution MUST verify unit tests pass without database connection configuration. Pull requests introducing query tests with database dependencies MUST be rejected. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-tests-verifying-exceptions-de9f.md b/.actual/rules/cross-cutting-tests-verifying-exceptions-de9f.md new file mode 100644 index 000000000000..3becf8ea545e --- /dev/null +++ b/.actual/rules/cross-cutting-tests-verifying-exceptions-de9f.md @@ -0,0 +1,36 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Verifying Exceptions + +These rules are ALWAYS ACTIVE for all unit tests in Bit.Core.AdminConsole, Bit.Commercial.Core.SecretsManager, and related test projects that verify asynchronous commands, queries, and repository operations using async/await patterns. + +### Rules + +- **R-ASYNC-TEST-001** MUST: Tests verifying exceptions from async methods MUST use `Assert.ThrowsAsync` with `await` rather than synchronous assertion methods. +- **R-ASYNC-TEST-002** MUST: Test methods invoking async system-under-test methods MUST be declared as `public async Task MethodName_Scenario_ExpectedResult()` and MUST use `await` when calling async SUT methods. +- **R-ASYNC-TEST-003** MUST: Mock verification with `Received()` MUST occur after awaiting system-under-test invocations to ensure correct call order validation. +- **R-ASYNC-TEST-004** SHOULD: Use `Arg.Is` with lambda expressions to validate collection contents and DateTime parameters in mock verification. + +### Verify + +```bash +# Count async test methods +grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count await usage with sutProvider.Sut +grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l + +# Count Assert.ThrowsAsync usage +grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +# Detect synchronous blocking patterns (should be zero) +grep -r '\.Result\|.Wait()' bitwarden_license/test/ --include='*.cs' | grep -v '//' | wc -l +``` + +**Accept when:** +- All test methods invoking async system-under-test methods are declared as `async Task` and use `await` +- Exception testing for async methods uses `Assert.ThrowsAsync` with `await` rather than synchronous assertions +- Mock verification with `Received()` occurs after awaiting system-under-test invocations in all test cases +- No synchronous blocking patterns (`.Result`, `.Wait()`) are present on Task-returning calls in test methods + + +Claude Code MUST NOT skip or defer verification. All async test methods MUST follow the async/await pattern with proper exception handling via Assert.ThrowsAsync. Violations detected during code review or static analysis MUST be corrected before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-typed-requirement-classes-b695.md b/.actual/rules/cross-cutting-typed-requirement-classes-b695.md new file mode 100644 index 000000000000..cac883b77b83 --- /dev/null +++ b/.actual/rules/cross-cutting-typed-requirement-classes-b695.md @@ -0,0 +1,40 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Typed Requirement Classes + +These rules are ALWAYS ACTIVE for all API controller endpoints requiring authorization in the AdminConsole API surface, specifically all controllers in the Bit.Api.AdminConsole.Controllers namespace and all HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests. + +### Rules + +- **R-TYPED-REQ-001** MUST: Typed requirement classes MUST be defined in the Bit.Api.AdminConsole.Authorization namespace or its subnamespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements). +- **R-TYPED-REQ-002** MUST: All controller methods in AdminConsole that access protected resources MUST have either [Authorize] or [AllowAnonymous] attributes. +- **R-TYPED-REQ-003** MUST: All requirement classes MUST follow the Requirement naming suffix convention (e.g., ManageUsersRequirement, ManagePoliciesRequirement). +- **R-TYPED-REQ-004** MUST: Controller methods MUST NOT use string-based Authorize(Policy = "...") attributes for authorization requirements. +- **R-TYPED-REQ-005** SHOULD: Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements. +- **R-TYPED-REQ-006** SHOULD: For endpoints requiring multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for imperative checks. +- **R-TYPED-REQ-007** SHOULD: Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits. +- **R-TYPED-REQ-008** SHOULD: Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic. + +### Verify + +```bash +# Count Authorize attributes in AdminConsole controllers +grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l + +# Count public async Task methods without authorization attributes +grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l + +# Count requirement classes in Authorization namespace +find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +# Verify no string-based policy attributes exist +grep -r "Authorize(Policy" src/Api/AdminConsole/Controllers/ | wc -l +``` + +**Accept when:** +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements +- Grep for undecorated public async Task methods returns 0 results (excluding AllowAnonymous and Authorize-decorated methods) + + +Claude Code MUST NOT skip or defer verification. Static analysis during CI pipeline using custom Roslyn analyzers or linting rules is mandatory. Code review must verify authorization attributes on all new endpoints. Security-focused integration tests must verify authorization enforcement for each endpoint. CI pipeline MUST fail if controller methods lack authorization attributes. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-unit-tests-query-8f98.md b/.actual/rules/cross-cutting-unit-tests-query-8f98.md new file mode 100644 index 000000000000..a0796ab9cad2 --- /dev/null +++ b/.actual/rules/cross-cutting-unit-tests-query-8f98.md @@ -0,0 +1,41 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Unit Tests Query + +These rules are ALWAYS ACTIVE for all unit tests in the Bit.Commercial.Core.Test suite that test query classes in the SecretsManager domain, particularly those coordinating access policy updates and secret synchronization operations. + +### Rules + +- **R-QUERY-001** MUST: Unit tests for query classes MUST invoke the system under test through its public interface method (e.g., GetAsync) and verify results without direct access to internal state. +- **R-QUERY-002** MUST: Query unit tests MUST use the sutProvider pattern to inject mock repository dependencies (ISecretRepository, IServiceAccountRepository) rather than instantiating concrete implementations. +- **R-QUERY-003** MUST: Test methods MUST follow the Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties. +- **R-QUERY-004** MUST: Query unit tests MUST NOT require database connections or external service dependencies during execution. +- **R-QUERY-005** SHOULD: Test methods SHOULD be named descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates). +- **R-QUERY-006** SHOULD: Test assertions SHOULD prioritize query result correctness (operation types, counts, data integrity) over exhaustive mock call verification. +- **R-QUERY-007** SHOULD: Critical repository interactions SHOULD be verified using Received() assertions to document expected interface contracts. +- **R-QUERY-008** MAY: Test doubles (hand-written fakes) MAY be used instead of mocking frameworks when repository interfaces stabilize and reusable test doubles reduce mock setup duplication. + +### Verify + +```bash +# Count sutProvider.Sut.GetAsync invocations in query test files +grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Count operation classification assertions +grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l + +# Execute query unit test suite +dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +# Detect direct repository instantiation in test code +grep -r 'new.*Repository' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | grep -v 'Substitute.For' | wc -l +``` + +**Accept when:** +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies +- No direct repository instantiation is detected in test code (only dependency injection via sutProvider) +- Individual test execution time does not exceed 100ms per test + + +Claude Code MUST NOT skip or defer verification. All rules in this file are mandatory for query unit tests in the SecretsManager domain. Code review and CI pipeline execution must confirm compliance before merge. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-unit-tests-use-bee1.md b/.actual/rules/cross-cutting-unit-tests-use-bee1.md new file mode 100644 index 000000000000..0d0665915e98 --- /dev/null +++ b/.actual/rules/cross-cutting-unit-tests-use-bee1.md @@ -0,0 +1,35 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Unit Tests Use + +These rules are ALWAYS ACTIVE for all API controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes and their corresponding unit test projects using Xunit framework. + +### Rules + +- **R-AUTH-001** MUST: Unit tests MUST use reflection-based helpers to verify authorization attributes on all controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes. +- **R-AUTH-002** MUST: All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST have appropriate authorization attributes from Microsoft.AspNetCore.Authorization or custom authorization implementations. +- **R-AUTH-003** MUST: Unit test helpers MUST validate both class-level [Authorize] attributes and method-level authorization on individual HTTP actions. +- **R-AUTH-004** MUST: Test failures MUST throw descriptive exceptions identifying specific controllers and methods lacking authorization. +- **R-AUTH-005** SHOULD: Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes. +- **R-AUTH-006** MAY: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) MAY use [AllowAnonymous] attribute with documented security review. + +### Verify + +```bash +# Count authorization test helper usage across test projects +grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l + +# Run authorization-specific unit tests +dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build + +# Count [Authorize] attributes applied to controllers +grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l +``` + +**Accept when:** +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers +- No HTTP action methods lack authorization attributes unless explicitly marked [AllowAnonymous] with documented exception + + +Claude Code MUST NOT skip or defer verification. Authorization attribute verification MUST execute during unit test runs and CI pipeline builds. Build failures MUST occur when authorization attributes are missing from any HTTP action method. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-unit-tests-verify-d040.md b/.actual/rules/cross-cutting-unit-tests-verify-d040.md new file mode 100644 index 000000000000..4f6ddf94855e --- /dev/null +++ b/.actual/rules/cross-cutting-unit-tests-verify-d040.md @@ -0,0 +1,39 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Unit Tests Verify + +These rules are ALWAYS ACTIVE for unit tests in services and commands that include ILogger dependencies, particularly in error conditions, edge cases, and exceptional flows where logging is expected. + +### Rules + +- **R-OBSV-001** MUST: Unit tests MUST verify that ILogger dependencies are invoked when testing components that perform logging operations. +- **R-OBSV-002** MUST: Logger verification MUST focus on error paths, security events, and operational alerts where log messages are part of the observable contract. +- **R-OBSV-003** SHOULD: Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure. +- **R-OBSV-004** SHOULD: Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.). +- **R-OBSV-005** SHOULD: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules. +- **R-OBSV-006** MAY: Document in test comments when logger verification is intentionally omitted for purely diagnostic logging, with team lead approval. + +### Verify + +```bash +# Count existing logger verification patterns in test files +grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts +- Error paths and operational events in components with ILogger dependencies have corresponding test assertions +- Test comments document intentional omissions of logger verification for purely diagnostic logging + + +Claude Code MUST NOT skip or defer verification of logger invocations in unit tests for observability components. All components with ILogger dependencies covering error conditions, security events, or operational alerts MUST have corresponding logger verification in their unit tests. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-use-logerror-level-2e07.md b/.actual/rules/cross-cutting-use-logerror-level-2e07.md new file mode 100644 index 000000000000..1bf7fef9256d --- /dev/null +++ b/.actual/rules/cross-cutting-use-logerror-level-2e07.md @@ -0,0 +1,36 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Use Logerror Level + +These rules are ALWAYS ACTIVE for controller methods decorated with `[Authorize]` or custom authorization requirements, operations involving external HTTP clients (IHttpClientFactory usage), and third-party service integrations (Stripe, external APIs) where failures must be logged without blocking primary operations. + +### Rules + +- **R-LOGERROR-001** SHOULD: Use LogError level for exceptions that represent operational failures requiring investigation, even if they do not block the user request. +- **R-LOGERROR-002** SHOULD: Include structured parameters (named placeholders) in log messages when logging external service failures, using entity IDs and URIs as contextual context (e.g., `{ProviderId}`, `{RequestUri}`). +- **R-LOGERROR-003** SHOULD: Wrap external service calls in try-catch blocks when the operation is non-critical, logging the exception with ILogger.LogError and at least one structured parameter. +- **R-LOGERROR-004** SHOULD: Inject `ILogger` via constructor dependency injection in all controller classes that interact with external services. +- **R-LOGERROR-005** MUST NOT: Log external service failures using unstructured string concatenation; use named placeholders matching parameter names instead. +- **R-LOGERROR-006** MUST NOT: Accidentally log sensitive data (tokens, API keys) in exception messages or structured parameters; review exception messages for PII/secrets before logging. + +### Verify + +```bash +# Find LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find try-catch blocks around external service calls with LogError +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-related tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' +``` + +**Accept when:** +- All controller methods with external service calls use `ILogger.LogError` with exception object and at least one structured parameter. +- External service failures in non-critical paths are caught and logged without propagating to the client. +- Log messages include contextual parameters using named placeholders matching the structured logging pattern (e.g., `_logger.LogError(ex, 'Failed for {ProviderId}', providerId)`). +- No LogError calls use string concatenation instead of structured parameters. +- Sensitive data (tokens, API keys) is not present in logged exception messages or parameters. + + +Claude Code MUST NOT skip or defer verification. All controller methods integrating with external services MUST be reviewed for compliance with structured logging requirements before acceptance. + \ No newline at end of file diff --git a/.actual/rules/cross-cutting-wrap-external-service-ce6b.md b/.actual/rules/cross-cutting-wrap-external-service-ce6b.md new file mode 100644 index 000000000000..36f08beddbe0 --- /dev/null +++ b/.actual/rules/cross-cutting-wrap-external-service-ce6b.md @@ -0,0 +1,39 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Wrap External Service + +These rules are ALWAYS ACTIVE for controller methods decorated with [Authorize] or custom authorization requirements, operations involving external HTTP clients (IHttpClientFactory usage), third-party service integrations (Stripe, external APIs), and multi-step operations where partial success is acceptable. + +### Rules + +- **R-EX-001** MUST: Wrap external service calls in try-catch blocks when the operation is non-critical to the primary request flow. +- **R-EX-002** MUST: Inject ILogger via constructor dependency injection in all controller classes that call external services. +- **R-EX-003** MUST: Use ILogger.LogError with exception object and at least one structured parameter (named placeholder) when logging external service failures. +- **R-EX-004** MUST: Include contextual parameters in log messages using named placeholders that match parameter names (e.g., {ProviderId}, {RequestUri}). +- **R-EX-005** SHOULD: Include context about primary operation state in log messages (e.g., 'Database updated successfully') to help correlate partial success scenarios. +- **R-EX-006** MUST NOT: Log sensitive data (tokens, API keys) in exception messages or parameters; use log scrubbing middleware and review exception messages for PII/secrets before logging. + +### Verify + +```bash +# Find LogError calls with structured parameters in controller files +grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ + +# Find try-catch blocks around external service calls with LogError +grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin + +# Run logging-specific tests with detailed output +dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +# Verify no string concatenation in LogError calls +grep -r 'LogError.*\+' --include='*.cs' src/ | grep -v '// exception' || echo 'No string concatenation found in LogError calls' +``` + +**Accept when:** +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern +- No sensitive data (tokens, API keys) appears in logged exception messages or parameters +- Primary operation state context is included in log messages for partial success scenarios + + +Claude Code MUST NOT skip or defer verification. All external service calls in controller methods MUST be wrapped in try-catch blocks with structured logging. Code review and static analysis rules MUST enforce this pattern before merge. + \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000000..40e218d0e14f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,55 @@ + +# Project ADRs + +This project's conventions are encoded as ADRs under `.actual/rules/`. **The ADRs ARE the pattern.** Follow them verbatim instead of reading existing implementations to figure out how to do something. + +> **Note:** this directive is calibrated for one-shot tasks (a single discrete feature). For multi-task interactive sessions, consult the ADRs for each task transition rather than holding to the per-session caps below. + +## Workflow (follow in order) + +1. **Identify topic.** Match the files you'll edit against the path-glob table below. Pick the 1-3 topics that match. Do not pre-emptively pick "related" topics; pick only what the file paths actually match. + +2. **Select ADRs by filename — the filename is the index.** Run `ls .actual/rules/`. Each filename is `--.md`; the `` (middle segment) names the ADR's specific concern — e.g., `database-schema-defined`, `zod-input-validation`, `cache-key-format`. + + **Scan ALL filenames first, then pick only the ones whose aspect-slug directly names a noun or verb in your task.** Select by filename; never read a body to decide relevance. **Hard cap: read at most 5 ADR files total.** If more than 5 look relevant, you are over-matching — keep the 5 most specific. + + **If the path-glob table below is a single `**/*` → `cross-cutting-` row** (one big bucket, no per-area topics), this filename scan is your ONLY filter. Do **not** read the bucket exhaustively — treat the filenames as a menu, match aspect-slugs to your task, read ≤5, and ignore the rest. Reading every ADR in the bucket is the exact failure this directive exists to prevent. + +3. **Locate insertion points (one read per file, max 3 files).** You may read source files ONLY to (a) find where to add code (which directory, which barrel export to update) or (b) look up an exact identifier you must import. **Do not read source files as pattern examples — the ADRs already encode the pattern.** If you find yourself reading a file because "I want to see how X is done elsewhere," stop. The ADR you already read tells you how. + +4. **Implement.** Write the code following the rule statements verbatim. If two ADRs seem to conflict, follow the more specific one (longer topic prefix wins). + +5. **Verify after implementing.** Only after the code is written, re-read the `verify_commands` or `accept_criteria` sections of the ADRs you applied and check your work against them. Run the verify commands if any. + +## Anti-patterns to avoid + +- Reading the first N rules alphabetically because they're cheap. Filter by aspect-slug first, then read only the relevant ones. +- Reading >5 ADR files for a single feature. If you're tempted, you're over-scoping the topic match. +- Reading the entire `cross-cutting-` bucket because "every rule is always active." Selection is by filename (step 2); you apply the ≤5 you selected, not all of them. +- Reading existing similar features to "see the pattern" — the ADRs encode the pattern. Trust them. +- Re-reading the same ADR multiple times. Cache it mentally. +- Continuing to browse the codebase after step 3. By step 4 you should be writing, not reading. + +Each rule file at `.actual/rules/--.md` contains the full ADR with rule statements, verify commands, and accept criteria. + +## Verification Protocol + +These rules are ALWAYS ACTIVE. Apply every rule **from the ADRs you selected in step 2** that governs the files you touch — to all code generation, modification, and review. "Always active" does **not** mean read every ADR: you apply the handful you selected by filename, within the read cap above. + +Every rule follows a **Verify → Fix → Repeat** loop. After generating or modifying code for any rule you MUST: + +1. **RUN** the rule's `### Verify` command(s). +2. **CAPTURE** the full output (stdout + stderr). +3. **EVALUATE** the output against the rule's **Accept when** criteria. +4. **IF FAILING:** diagnose the root cause, apply a fix, and re-run from step 1. +5. **IF PASSING:** keep the passing output as evidence before moving on. +6. **MAX ITERATIONS:** 5 attempts per rule. If still failing after 5 attempts, STOP and report the failure with all captured output. + +Compliance is not optional. Do not skip verification, assume correctness, or defer it to a later task. Every change to a governed area must be accompanied by a passing verification run. + +## Path glob → topic + +| You're editing | Topic prefix | +|---|---| +| `**/*` | `cross-cutting-` _(306 ADRs)_ | + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000000..40e218d0e14f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ + +# Project ADRs + +This project's conventions are encoded as ADRs under `.actual/rules/`. **The ADRs ARE the pattern.** Follow them verbatim instead of reading existing implementations to figure out how to do something. + +> **Note:** this directive is calibrated for one-shot tasks (a single discrete feature). For multi-task interactive sessions, consult the ADRs for each task transition rather than holding to the per-session caps below. + +## Workflow (follow in order) + +1. **Identify topic.** Match the files you'll edit against the path-glob table below. Pick the 1-3 topics that match. Do not pre-emptively pick "related" topics; pick only what the file paths actually match. + +2. **Select ADRs by filename — the filename is the index.** Run `ls .actual/rules/`. Each filename is `--.md`; the `` (middle segment) names the ADR's specific concern — e.g., `database-schema-defined`, `zod-input-validation`, `cache-key-format`. + + **Scan ALL filenames first, then pick only the ones whose aspect-slug directly names a noun or verb in your task.** Select by filename; never read a body to decide relevance. **Hard cap: read at most 5 ADR files total.** If more than 5 look relevant, you are over-matching — keep the 5 most specific. + + **If the path-glob table below is a single `**/*` → `cross-cutting-` row** (one big bucket, no per-area topics), this filename scan is your ONLY filter. Do **not** read the bucket exhaustively — treat the filenames as a menu, match aspect-slugs to your task, read ≤5, and ignore the rest. Reading every ADR in the bucket is the exact failure this directive exists to prevent. + +3. **Locate insertion points (one read per file, max 3 files).** You may read source files ONLY to (a) find where to add code (which directory, which barrel export to update) or (b) look up an exact identifier you must import. **Do not read source files as pattern examples — the ADRs already encode the pattern.** If you find yourself reading a file because "I want to see how X is done elsewhere," stop. The ADR you already read tells you how. + +4. **Implement.** Write the code following the rule statements verbatim. If two ADRs seem to conflict, follow the more specific one (longer topic prefix wins). + +5. **Verify after implementing.** Only after the code is written, re-read the `verify_commands` or `accept_criteria` sections of the ADRs you applied and check your work against them. Run the verify commands if any. + +## Anti-patterns to avoid + +- Reading the first N rules alphabetically because they're cheap. Filter by aspect-slug first, then read only the relevant ones. +- Reading >5 ADR files for a single feature. If you're tempted, you're over-scoping the topic match. +- Reading the entire `cross-cutting-` bucket because "every rule is always active." Selection is by filename (step 2); you apply the ≤5 you selected, not all of them. +- Reading existing similar features to "see the pattern" — the ADRs encode the pattern. Trust them. +- Re-reading the same ADR multiple times. Cache it mentally. +- Continuing to browse the codebase after step 3. By step 4 you should be writing, not reading. + +Each rule file at `.actual/rules/--.md` contains the full ADR with rule statements, verify commands, and accept criteria. + +## Verification Protocol + +These rules are ALWAYS ACTIVE. Apply every rule **from the ADRs you selected in step 2** that governs the files you touch — to all code generation, modification, and review. "Always active" does **not** mean read every ADR: you apply the handful you selected by filename, within the read cap above. + +Every rule follows a **Verify → Fix → Repeat** loop. After generating or modifying code for any rule you MUST: + +1. **RUN** the rule's `### Verify` command(s). +2. **CAPTURE** the full output (stdout + stderr). +3. **EVALUATE** the output against the rule's **Accept when** criteria. +4. **IF FAILING:** diagnose the root cause, apply a fix, and re-run from step 1. +5. **IF PASSING:** keep the passing output as evidence before moving on. +6. **MAX ITERATIONS:** 5 attempts per rule. If still failing after 5 attempts, STOP and report the failure with all captured output. + +Compliance is not optional. Do not skip verification, assume correctness, or defer it to a later task. Every change to a governed area must be accompanied by a passing verification run. + +## Path glob → topic + +| You're editing | Topic prefix | +|---|---| +| `**/*` | `cross-cutting-` _(306 ADRs)_ | + diff --git a/docs/adr/0144da07-6cd7-45ba-9cd7-f0584aa34ead-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-apply-custom.md b/docs/adr/0144da07-6cd7-45ba-9cd7-f0584aa34ead-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-apply-custom.md new file mode 100644 index 000000000000..a8849306de6e --- /dev/null +++ b/docs/adr/0144da07-6cd7-45ba-9cd7-f0584aa34ead-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-apply-custom.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Apply Custom + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MUST: Controllers MUST apply custom authorization requirements via Authorize attributes at the method level for endpoint-level access control + +## Policy Block + +- MUST Controllers MUST apply custom authorization requirements via Authorize attributes at the method level for endpoint-level access control + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/03460212-4b7e-492f-8a14-fa879008634d-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-specific.md b/docs/adr/03460212-4b7e-492f-8a14-fa879008634d-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-specific.md new file mode 100644 index 000000000000..d5e4cd5e5286 --- /dev/null +++ b/docs/adr/03460212-4b7e-492f-8a14-fa879008634d-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-specific.md @@ -0,0 +1,116 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Tests Verify Specific + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Unit tests in the codebase verify that logger dependencies are invoked with expected warning messages during error conditions +- The pattern appears in test files for SCIM group operations (PatchGroupCommandTests.cs) and authentication request services (AuthRequestServiceTests.cs) +- Tests use dependency injection providers to retrieve ILogger instances and assert that specific log methods (LogWarning) are called with exact message strings +- This testing approach treats logging as a verifiable behavior rather than an implementation detail, ensuring observability contracts are maintained + +## Problem Statement + +Without explicit verification of logging behavior in unit tests, critical diagnostic messages may be removed or modified during refactoring, degrading operational observability and making production issues harder to diagnose. The codebase needs a consistent approach to ensure logging contracts are tested alongside business logic. + +## Decision + +1. SHOULD: Tests SHOULD verify the specific log level (LogWarning, LogError, etc.) and message content when the exact message is part of the observable contract + +## Policy Block + +- SHOULD Tests SHOULD verify the specific log level (LogWarning, LogError, etc.) and message content when the exact message is part of the observable contract + +In scope: +- Unit tests for services and commands that include ILogger dependencies +- Test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected +- Components in the Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging + +Out of scope: +- Integration tests where actual logging infrastructure is used rather than mocked +- Performance tests where logger verification overhead is unacceptable +- Tests for components that do not have logging dependencies +- Logging infrastructure implementation tests (e.g., testing the logger itself) + +Exceptions: +- EX-001: The logging behavior is purely diagnostic and not part of any operational contract or alerting logic + +## Rationale + +- The evidence shows 2 test files explicitly verifying ILogger invocations with specific messages, indicating an established pattern for treating logging as testable behavior +- Verifying logger calls ensures that operational observability contracts are maintained across refactoring and code changes +- The pattern uses dependency injection and mocking frameworks (AutoFixture, NSubstitute) already present in the codebase, requiring no additional infrastructure +- Testing logging behavior provides early detection of changes that could impact production diagnostics and incident response + +## Consequences + +Positive: +- Logging contracts become explicit and protected by automated tests, preventing silent degradation of observability +- Developers receive immediate feedback when refactoring removes or changes critical diagnostic messages +- The pattern integrates naturally with existing dependency injection and unit testing infrastructure +- Production incident response is improved through guaranteed availability of expected log messages + +Negative: +- Unit tests become coupled to logging implementation details, potentially increasing test maintenance burden +- Test verbosity increases as logger verification adds additional assertions to each test case +- Refactoring log messages requires updating corresponding test assertions, slowing down minor message improvements +- Over-specification of logging behavior may discourage developers from adding helpful diagnostic logging + +## Alternatives + +- Treat logging as an implementation detail and do not verify logger invocations in unit tests (rejected) + Rejected because: This approach allows critical diagnostic messages to be removed during refactoring without detection, degrading production observability. The evidence shows the codebase has already adopted explicit logger verification. + When valid: For purely diagnostic logging that has no operational significance and is not used for alerting or incident response +- Use integration tests with actual logging infrastructure to verify log output (deferred) + Rejected because: Integration tests provide slower feedback and higher maintenance cost. This approach complements rather than replaces unit-level verification. + When valid: For end-to-end validation of logging configuration, formatting, and sink behavior in staging environments +- Implement custom logging abstractions that separate testable events from log formatting (rejected) + Rejected because: This requires significant infrastructure changes and abstracts away the ILogger pattern already established in the codebase. The current approach works with existing dependencies. + When valid: For greenfield projects or major logging infrastructure redesigns where decoupling events from formatting provides clear architectural benefits + +## Risks + +- Over-specification of log messages in tests creates brittleness, where minor message improvements require widespread test updates + Mitigation: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules + Owner: Engineering team +- Developers may avoid adding helpful logging to avoid increasing test complexity and maintenance burden + Mitigation: Establish clear guidelines on which logging calls require verification (error conditions, security events, operational alerts) versus which are purely diagnostic + Owner: Engineering team and tech leads +- Logger verification may not catch issues with log message formatting, structured logging parameters, or sink configuration + Mitigation: Complement unit-level logger verification with integration tests that validate actual log output in representative environments + Owner: QA and engineering team + +## Implementation Notes + +- Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure +- Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.) +- Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract +- Document in test comments when logger verification is intentionally omitted for purely diagnostic logging +- Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns + +## Continuation Context + + +Verify commands: +- grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts + +## Enforcement + +- Verified by: Code review checks for logger verification in unit tests covering error conditions and operational events +- Verified by: CI pipeline runs unit tests that include logger verification assertions +- Verified by: Static analysis or custom linting rules to detect ILogger dependencies without corresponding test verification +- Violation handling: Code review feedback requests addition of logger verification for components with ILogger dependencies +- Violation handling: Pull requests may be blocked if critical error paths lack logging verification +- Violation handling: Retrospective analysis of production incidents identifies missing logging that should have been tested +- Exception process: Developer documents in test comments why logger verification is omitted (e.g., purely diagnostic logging) +- Exception process: Team lead approves exception during code review based on operational significance assessment +- Exception process: Exception is recorded in test file comments for future reference \ No newline at end of file diff --git a/docs/adr/03d051fd-23a0-4eb5-b917-18767dc87480-enforce-authorization-attributes-on-api-controllers-via-unit-tests-test-helpers-report.md b/docs/adr/03d051fd-23a0-4eb5-b917-18767dc87480-enforce-authorization-attributes-on-api-controllers-via-unit-tests-test-helpers-report.md new file mode 100644 index 000000000000..116ea4de656a --- /dev/null +++ b/docs/adr/03d051fd-23a0-4eb5-b917-18767dc87480-enforce-authorization-attributes-on-api-controllers-via-unit-tests-test-helpers-report.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Test Helpers Report + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. SHOULD: Test helpers SHOULD report all missing authorization attributes in a single test failure rather than failing on the first violation + +## Policy Block + +- SHOULD Test helpers SHOULD report all missing authorization attributes in a single test failure rather than failing on the first violation + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/052d6875-cc91-4f25-b7be-7a8e5370916f-use-structured-logging-with-contextual-parameters-for-external-service-failures-include-structured-contextual.md b/docs/adr/052d6875-cc91-4f25-b7be-7a8e5370916f-use-structured-logging-with-contextual-parameters-for-external-service-failures-include-structured-contextual.md new file mode 100644 index 000000000000..28fb25272c9b --- /dev/null +++ b/docs/adr/052d6875-cc91-4f25-b7be-7a8e5370916f-use-structured-logging-with-contextual-parameters-for-external-service-failures-include-structured-contextual.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Include Structured Contextual + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. MUST: Include structured contextual parameters in log messages using named placeholders (e.g., {ProviderId}, {RequestUri}) that correspond to method arguments + +## Policy Block + +- MUST Include structured contextual parameters in log messages using named placeholders (e.g., {ProviderId}, {RequestUri}) that correspond to method arguments + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/05a53096-c159-4325-aee5-9c6a1acd88df-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-public-endpoints-that.md b/docs/adr/05a53096-c159-4325-aee5-9c6a1acd88df-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-public-endpoints-that.md new file mode 100644 index 000000000000..77ba8dcaedb3 --- /dev/null +++ b/docs/adr/05a53096-c159-4325-aee5-9c6a1acd88df-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-public-endpoints-that.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Public Endpoints That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. MAY: Public endpoints that do not require authentication MAY omit authorization attributes, but MUST be explicitly documented as public access points + +## Policy Block + +- MAY Public endpoints that do not require authentication MAY omit authorization attributes, but MUST be explicitly documented as public access points + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/065cedd3-19a8-40d8-a11f-e45077be274a-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-rsa-key-operations.md b/docs/adr/065cedd3-19a8-40d8-a11f-e45077be274a-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-rsa-key-operations.md new file mode 100644 index 000000000000..7e8d48b8290d --- /dev/null +++ b/docs/adr/065cedd3-19a8-40d8-a11f-e45077be274a-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-rsa-key-operations.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Rsa Key Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. MUST: RSA key operations MUST use a managed pool (RSA_POOL) to coordinate resource lifecycle + +## Policy Block + +- MUST RSA key operations MUST use a managed pool (RSA_POOL) to coordinate resource lifecycle + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/07bef05b-46f9-49a1-8146-08515ab97e21-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-returning.md b/docs/adr/07bef05b-46f9-49a1-8146-08515ab97e21-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-returning.md new file mode 100644 index 000000000000..b7a88cd0137e --- /dev/null +++ b/docs/adr/07bef05b-46f9-49a1-8146-08515ab97e21-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-returning.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Functions Returning + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. MUST: FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function + +## Policy Block + +- MUST FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/0929cc83-dbde-4cc8-823b-acab2af6ef9e-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-log-successful.md b/docs/adr/0929cc83-dbde-4cc8-823b-acab2af6ef9e-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-log-successful.md new file mode 100644 index 000000000000..f5aaced89d73 --- /dev/null +++ b/docs/adr/0929cc83-dbde-4cc8-823b-acab2af6ef9e-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-log-successful.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Log Successful + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. MAY: Controllers MAY log successful authorization decisions at Debug or Trace level for detailed audit trails in non-production environments + +## Policy Block + +- MAY Controllers MAY log successful authorization decisions at Debug or Trace level for detailed audit trails in non-production environments + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/0931104c-fe38-4781-b9f7-a75a7a4e7450-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-logging-statements-validation.md b/docs/adr/0931104c-fe38-4781-b9f7-a75a7a4e7450-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-logging-statements-validation.md new file mode 100644 index 000000000000..98fc7b83fc14 --- /dev/null +++ b/docs/adr/0931104c-fe38-4781-b9f7-a75a7a4e7450-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-logging-statements-validation.md @@ -0,0 +1,116 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Logging Statements Validation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The push notification service (IPushNotificationService) processes notifications from multiple domain entities including AdminConsole, Auth, and NotificationCenter modules within the Bit.Core namespace +- Invalid notification states (invalid notification ID and invalid notification status ID) are encountered during runtime processing and require observable quality gates +- The codebase uses structured logging with ILogger to record warning-level events when validation failures occur during push notification processing +- A pragma warning disable directive (B) is present, indicating intentional suppression of specific compiler or analyzer warnings in this quality-critical path + +## Problem Statement + +Push notification services must detect and record invalid notification states (malformed IDs or invalid status values) at runtime to enable operational visibility, debugging, and quality assurance, while balancing the need to suppress specific static analysis warnings that may conflict with the chosen logging strategy. + +## Decision + +1. SHOULD: Logging statements for validation failures SHOULD use structured logging templates with named parameters (e.g., {NotificationId}) rather than string interpolation + +## Policy Block + +- SHOULD Logging statements for validation failures SHOULD use structured logging templates with named parameters (e.g., {NotificationId}) rather than string interpolation + +In scope: +- All implementations of IPushNotificationService interface +- Push notification processing logic handling Bit.Core.NotificationCenter.Entities +- Validation logic for notification IDs and status IDs +- Runtime quality gates for notification state verification + +Out of scope: +- Logging for successful notification processing (use Info or Debug levels) +- Error-level logging for system failures or exceptions +- Validation logic in non-push notification contexts +- Static analysis warning suppression for non-quality-gate purposes + +Exceptions: +- EXC-001: High-frequency notification processing paths where warning-level logging would create excessive log volume + +## Rationale + +- The evidence shows consistent use of ILogger.LogWarning with structured parameters for two distinct invalid notification scenarios, establishing a quality gate pattern for runtime validation +- Push notifications cross multiple domain boundaries (AdminConsole, Auth, NotificationCenter entities), requiring observable validation points to trace failures across module boundaries +- Warning-level logging provides operational visibility without triggering error alerting, appropriate for validation failures that may be recoverable or expected in certain edge cases +- The presence of pragma warning disable B indicates intentional acceptance of static analysis warnings in favor of the runtime observability pattern + +## Consequences + +Positive: +- Operational teams gain visibility into invalid notification states without manual debugging or code instrumentation +- Structured logging with notification IDs enables correlation of validation failures with specific notification instances across distributed logs +- Consistent warning-level logging establishes a quality gate that can be monitored, alerted on, and analyzed for trends +- Cross-module validation failures become observable at the push service boundary, simplifying root cause analysis + +Negative: +- Warning-level logs may accumulate in high-volume notification scenarios, increasing log storage costs and noise +- Suppression of static analysis warnings (pragma disable) reduces compile-time safety checks and may mask related code quality issues +- Developers must maintain discipline to use structured logging templates rather than simpler string concatenation +- The pattern creates a dependency on logging infrastructure availability for quality gate observability + +## Alternatives + +- Use exception throwing for invalid notification states instead of warning-level logging (rejected) + Rejected because: Exceptions would disrupt notification processing flow and trigger error-level alerting for potentially recoverable validation failures, creating operational noise + When valid: When invalid notification states represent unrecoverable errors that should halt processing +- Implement metrics-based counters for invalid notifications without detailed logging (rejected) + Rejected because: Metrics alone lack the contextual detail (specific notification IDs) needed for debugging individual validation failures + When valid: As a complementary approach for high-level trend monitoring alongside detailed logging +- Use Debug-level logging for validation failures (rejected) + Rejected because: Debug-level logs are typically disabled in production, eliminating operational visibility into validation failures + When valid: In development or staging environments where verbose logging is acceptable + +## Risks + +- High-frequency invalid notifications could generate excessive log volume, impacting log infrastructure performance and costs + Mitigation: Implement log sampling or rate limiting for validation warnings if frequency exceeds operational thresholds; monitor log volume metrics + Owner: Platform engineering team +- Pragma warning suppression may mask legitimate code quality issues flagged by static analysis + Mitigation: Document specific warning codes being suppressed; periodically review suppressed warnings to ensure they remain justified + Owner: Code quality team +- Inconsistent application of logging pattern across different notification entity types could create observability gaps + Mitigation: Implement automated verification (linting or testing) to ensure all notification validation paths include structured warning logs + Owner: Engineering team + +## Implementation Notes + +- Use ILogger interface with structured logging templates: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id) +- Apply the pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities +- Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern +- Consider implementing log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform + +## Continuation Context + + +Verify commands: +- grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' +- grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' +- find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; + +Accept when: +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate + +## Enforcement + +- Verified by: Code review checklist requiring structured warning logs for all notification validation failures +- Verified by: Automated grep-based verification in CI pipeline checking for LogWarning patterns in push notification services +- Verified by: Static analysis configuration review to ensure pragma warning suppressions are documented +- Violation handling: Code review rejection if validation failures lack warning-level logging with structured parameters +- Violation handling: CI pipeline warnings if push notification services are modified without corresponding logging verification +- Violation handling: Quarterly audit of pragma warning suppressions to ensure they remain justified and documented +- Exception process: Submit exception request to platform architecture team with performance impact analysis for high-frequency paths +- Exception process: Provide alternative observability mechanism (metrics, sampling strategy) in exception request +- Exception process: Document approved exceptions in service-level README with rationale and compensating controls \ No newline at end of file diff --git a/docs/adr/09afc0f6-e646-46ab-b05d-69adb04ccfd7-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md b/docs/adr/09afc0f6-e646-46ab-b05d-69adb04ccfd7-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md new file mode 100644 index 000000000000..1d5b65b2b1fa --- /dev/null +++ b/docs/adr/09afc0f6-e646-46ab-b05d-69adb04ccfd7-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md @@ -0,0 +1,116 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Push Notification Services + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The push notification service (IPushNotificationService) processes notifications from multiple domain entities including AdminConsole, Auth, and NotificationCenter modules within the Bit.Core namespace +- Invalid notification states (invalid notification ID and invalid notification status ID) are encountered during runtime processing and require observable quality gates +- The codebase uses structured logging with ILogger to record warning-level events when validation failures occur during push notification processing +- A pragma warning disable directive (B) is present, indicating intentional suppression of specific compiler or analyzer warnings in this quality-critical path + +## Problem Statement + +Push notification services must detect and record invalid notification states (malformed IDs or invalid status values) at runtime to enable operational visibility, debugging, and quality assurance, while balancing the need to suppress specific static analysis warnings that may conflict with the chosen logging strategy. + +## Decision + +1. MUST: Push notification services MUST log warning-level events when encountering invalid notification IDs using structured logging with the notification ID as a parameter + +## Policy Block + +- MUST Push notification services MUST log warning-level events when encountering invalid notification IDs using structured logging with the notification ID as a parameter + +In scope: +- All implementations of IPushNotificationService interface +- Push notification processing logic handling Bit.Core.NotificationCenter.Entities +- Validation logic for notification IDs and status IDs +- Runtime quality gates for notification state verification + +Out of scope: +- Logging for successful notification processing (use Info or Debug levels) +- Error-level logging for system failures or exceptions +- Validation logic in non-push notification contexts +- Static analysis warning suppression for non-quality-gate purposes + +Exceptions: +- EXC-001: High-frequency notification processing paths where warning-level logging would create excessive log volume + +## Rationale + +- The evidence shows consistent use of ILogger.LogWarning with structured parameters for two distinct invalid notification scenarios, establishing a quality gate pattern for runtime validation +- Push notifications cross multiple domain boundaries (AdminConsole, Auth, NotificationCenter entities), requiring observable validation points to trace failures across module boundaries +- Warning-level logging provides operational visibility without triggering error alerting, appropriate for validation failures that may be recoverable or expected in certain edge cases +- The presence of pragma warning disable B indicates intentional acceptance of static analysis warnings in favor of the runtime observability pattern + +## Consequences + +Positive: +- Operational teams gain visibility into invalid notification states without manual debugging or code instrumentation +- Structured logging with notification IDs enables correlation of validation failures with specific notification instances across distributed logs +- Consistent warning-level logging establishes a quality gate that can be monitored, alerted on, and analyzed for trends +- Cross-module validation failures become observable at the push service boundary, simplifying root cause analysis + +Negative: +- Warning-level logs may accumulate in high-volume notification scenarios, increasing log storage costs and noise +- Suppression of static analysis warnings (pragma disable) reduces compile-time safety checks and may mask related code quality issues +- Developers must maintain discipline to use structured logging templates rather than simpler string concatenation +- The pattern creates a dependency on logging infrastructure availability for quality gate observability + +## Alternatives + +- Use exception throwing for invalid notification states instead of warning-level logging (rejected) + Rejected because: Exceptions would disrupt notification processing flow and trigger error-level alerting for potentially recoverable validation failures, creating operational noise + When valid: When invalid notification states represent unrecoverable errors that should halt processing +- Implement metrics-based counters for invalid notifications without detailed logging (rejected) + Rejected because: Metrics alone lack the contextual detail (specific notification IDs) needed for debugging individual validation failures + When valid: As a complementary approach for high-level trend monitoring alongside detailed logging +- Use Debug-level logging for validation failures (rejected) + Rejected because: Debug-level logs are typically disabled in production, eliminating operational visibility into validation failures + When valid: In development or staging environments where verbose logging is acceptable + +## Risks + +- High-frequency invalid notifications could generate excessive log volume, impacting log infrastructure performance and costs + Mitigation: Implement log sampling or rate limiting for validation warnings if frequency exceeds operational thresholds; monitor log volume metrics + Owner: Platform engineering team +- Pragma warning suppression may mask legitimate code quality issues flagged by static analysis + Mitigation: Document specific warning codes being suppressed; periodically review suppressed warnings to ensure they remain justified + Owner: Code quality team +- Inconsistent application of logging pattern across different notification entity types could create observability gaps + Mitigation: Implement automated verification (linting or testing) to ensure all notification validation paths include structured warning logs + Owner: Engineering team + +## Implementation Notes + +- Use ILogger interface with structured logging templates: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id) +- Apply the pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities +- Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern +- Consider implementing log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform + +## Continuation Context + + +Verify commands: +- grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' +- grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' +- find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; + +Accept when: +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate + +## Enforcement + +- Verified by: Code review checklist requiring structured warning logs for all notification validation failures +- Verified by: Automated grep-based verification in CI pipeline checking for LogWarning patterns in push notification services +- Verified by: Static analysis configuration review to ensure pragma warning suppressions are documented +- Violation handling: Code review rejection if validation failures lack warning-level logging with structured parameters +- Violation handling: CI pipeline warnings if push notification services are modified without corresponding logging verification +- Violation handling: Quarterly audit of pragma warning suppressions to ensure they remain justified and documented +- Exception process: Submit exception request to platform architecture team with performance impact analysis for high-frequency paths +- Exception process: Provide alternative observability mechanism (metrics, sampling strategy) in exception request +- Exception process: Document approved exceptions in service-level README with rationale and compensating controls \ No newline at end of file diff --git a/docs/adr/0aeea845-ad1a-44d3-a49f-f78e57388421-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-base64-encoding-decoding.md b/docs/adr/0aeea845-ad1a-44d3-a49f-f78e57388421-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-base64-encoding-decoding.md new file mode 100644 index 000000000000..b9f89156c11e --- /dev/null +++ b/docs/adr/0aeea845-ad1a-44d3-a49f-f78e57388421-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-base64-encoding-decoding.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Base64 Encoding Decoding + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. SHOULD: Base64 encoding/decoding of binary cryptographic data crossing FFI boundaries SHOULD use the standard engine from the base64 crate for consistent encoding behavior + +## Policy Block + +- SHOULD Base64 encoding/decoding of binary cryptographic data crossing FFI boundaries SHOULD use the standard engine from the base64 crate for consistent encoding behavior + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/0ca06cfe-e64d-42d3-b847-78554bc2595f-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-accepting.md b/docs/adr/0ca06cfe-e64d-42d3-b847-78554bc2595f-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-accepting.md new file mode 100644 index 000000000000..a22b3b6ceb73 --- /dev/null +++ b/docs/adr/0ca06cfe-e64d-42d3-b847-78554bc2595f-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-accepting.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Functions Accepting + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. MUST: All FFI functions accepting c_char pointers MUST validate input using CStr::from_ptr before dereferencing or converting to Rust types + +## Policy Block + +- MUST All FFI functions accepting c_char pointers MUST validate input using CStr::from_ptr before dereferencing or converting to Rust types + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/0cb98c9c-8648-4035-b801-527526b20ada-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authorization-policies-require.md b/docs/adr/0cb98c9c-8648-4035-b801-527526b20ada-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authorization-policies-require.md new file mode 100644 index 000000000000..7794ab705c16 --- /dev/null +++ b/docs/adr/0cb98c9c-8648-4035-b801-527526b20ada-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authorization-policies-require.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authorization Policies Require + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. MUST: Authorization policies MUST require authenticated users and enforce scope claims using RequireClaim with JwtClaimTypes.Scope value 'api.scim' + +## Policy Block + +- MUST Authorization policies MUST require authenticated users and enforce scope claims using RequireClaim with JwtClaimTypes.Scope value 'api.scim' + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/0d1f5b18-b490-49be-8e39-8faaa1e2424f-standardize-authorization-policy-configuration-with-named-scopes-production-authorization-policies.md b/docs/adr/0d1f5b18-b490-49be-8e39-8faaa1e2424f-standardize-authorization-policy-configuration-with-named-scopes-production-authorization-policies.md new file mode 100644 index 000000000000..294f311ffdbc --- /dev/null +++ b/docs/adr/0d1f5b18-b490-49be-8e39-8faaa1e2424f-standardize-authorization-policy-configuration-with-named-scopes-production-authorization-policies.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Production Authorization Policies + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. MUST: Production authorization policies MUST require authenticated users via RequireAuthenticatedUser() + +## Policy Block + +- MUST Production authorization policies MUST require authenticated users via RequireAuthenticatedUser() + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/100f3767-af9d-45f5-885f-9a4456ace179-enforce-authorization-attributes-on-api-controllers-via-unit-tests-controllers-have-class.md b/docs/adr/100f3767-af9d-45f5-885f-9a4456ace179-enforce-authorization-attributes-on-api-controllers-via-unit-tests-controllers-have-class.md new file mode 100644 index 000000000000..4801421b4273 --- /dev/null +++ b/docs/adr/100f3767-af9d-45f5-885f-9a4456ace179-enforce-authorization-attributes-on-api-controllers-via-unit-tests-controllers-have-class.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Controllers Have Class + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. MUST: All API controllers MUST have a class-level [Authorize] attribute unless explicitly exempted by documented exception + +## Policy Block + +- MUST All API controllers MUST have a class-level [Authorize] attribute unless explicitly exempted by documented exception + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/10d29bf0-d5fa-475e-9947-741b253d41f4-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-modules-use.md b/docs/adr/10d29bf0-d5fa-475e-9947-741b253d41f4-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-modules-use.md new file mode 100644 index 000000000000..59caf9fbd4b2 --- /dev/null +++ b/docs/adr/10d29bf0-d5fa-475e-9947-741b253d41f4-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-modules-use.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Ffi Modules Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. MAY: FFI modules MAY use std::collections::HashSet for tracking allocated resources to detect double-free attempts in debug builds + +## Policy Block + +- MAY FFI modules MAY use std::collections::HashSet for tracking allocated resources to detect double-free attempts in debug builds + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/1246ffac-4184-4102-bae0-11c0852aef3d-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md b/docs/adr/1246ffac-4184-4102-bae0-11c0852aef3d-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md new file mode 100644 index 000000000000..0a49df819014 --- /dev/null +++ b/docs/adr/1246ffac-4184-4102-bae0-11c0852aef3d-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Service Registration + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. SHOULD: Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to allow override by consuming applications + +## Policy Block + +- SHOULD Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to allow override by consuming applications + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/129355f1-5bef-4966-8db2-3b85d084cd4c-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-code-exercising.md b/docs/adr/129355f1-5bef-4966-8db2-3b85d084cd4c-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-code-exercising.md new file mode 100644 index 000000000000..b1644fc74050 --- /dev/null +++ b/docs/adr/129355f1-5bef-4966-8db2-3b85d084cd4c-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-code-exercising.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Test Code Exercising + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. MUST: Test code exercising RSA cryptographic operations in public API protocols MUST use embedded fake RSA keys with the naming pattern _FAKE_RSA_KEY_N where N is a zero-indexed integer + +## Policy Block + +- MUST Test code exercising RSA cryptographic operations in public API protocols MUST use embedded fake RSA keys with the naming pattern _FAKE_RSA_KEY_N where N is a zero-indexed integer + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/12ca8d34-55df-4dd0-accb-6f82613bb8d6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-string-validation-failures.md b/docs/adr/12ca8d34-55df-4dd0-accb-6f82613bb8d6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-string-validation-failures.md new file mode 100644 index 000000000000..0ca017691963 --- /dev/null +++ b/docs/adr/12ca8d34-55df-4dd0-accb-6f82613bb8d6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-string-validation-failures.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: String Validation Failures + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. MUST: String validation failures at FFI boundaries MUST return error codes or null pointers rather than panicking + +## Policy Block + +- MUST String validation failures at FFI boundaries MUST return error codes or null pointers rather than panicking + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/1404fbba-3345-4129-a549-1e89fd72a4fa-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-endpoints.md b/docs/adr/1404fbba-3345-4129-a549-1e89fd72a4fa-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-endpoints.md new file mode 100644 index 000000000000..ba2239666078 --- /dev/null +++ b/docs/adr/1404fbba-3345-4129-a549-1e89fd72a4fa-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-endpoints.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Billing Endpoints + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. MUST: All organization billing endpoints MUST be decorated with [Authorize] to enforce organization-scoped billing authorization + +## Policy Block + +- MUST All organization billing endpoints MUST be decorated with [Authorize] to enforce organization-scoped billing authorization + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/14d355fa-4151-47ec-be57-af33dec27278-standardize-authorization-policy-configuration-with-named-scopes-named-authorization-policies.md b/docs/adr/14d355fa-4151-47ec-be57-af33dec27278-standardize-authorization-policy-configuration-with-named-scopes-named-authorization-policies.md new file mode 100644 index 000000000000..450f157ed45f --- /dev/null +++ b/docs/adr/14d355fa-4151-47ec-be57-af33dec27278-standardize-authorization-policy-configuration-with-named-scopes-named-authorization-policies.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Named Authorization Policies + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. SHOULD: Named authorization policies SHOULD correspond to functional boundaries (e.g., 'Scim' for SCIM API endpoints) + +## Policy Block + +- SHOULD Named authorization policies SHOULD correspond to functional boundaries (e.g., 'Scim' for SCIM API endpoints) + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/155e3926-1c5d-48a3-bd0f-17d5c45398f1-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-apply-authorization.md b/docs/adr/155e3926-1c5d-48a3-bd0f-17d5c45398f1-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-apply-authorization.md new file mode 100644 index 000000000000..2ad769ebb3aa --- /dev/null +++ b/docs/adr/155e3926-1c5d-48a3-bd0f-17d5c45398f1-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-apply-authorization.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Apply Authorization + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. MUST: Controllers MUST apply authorization attributes at the action method level using the syntax [Authorize] where TRequirement represents the specific permission required + +## Policy Block + +- MUST Controllers MUST apply authorization attributes at the action method level using the syntax [Authorize] where TRequirement represents the specific permission required + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/15e40d0d-ad1f-48d7-93c8-4a2a34a133b1-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md b/docs/adr/15e40d0d-ad1f-48d7-93c8-4a2a34a133b1-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md new file mode 100644 index 000000000000..1e18c39c66ed --- /dev/null +++ b/docs/adr/15e40d0d-ad1f-48d7-93c8-4a2a34a133b1-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. SHOULD: Fake RSA keys SHOULD be co-located with the cryptographic implementation code they test, within the same module or adjacent test module + +## Policy Block + +- SHOULD Fake RSA keys SHOULD be co-located with the cryptographic implementation code they test, within the same module or adjacent test module + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/16aa9187-10a7-4726-9b4c-ec41d1641aaa-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-shared-cryptographic-resources.md b/docs/adr/16aa9187-10a7-4726-9b4c-ec41d1641aaa-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-shared-cryptographic-resources.md new file mode 100644 index 000000000000..e0e617bfcddb --- /dev/null +++ b/docs/adr/16aa9187-10a7-4726-9b4c-ec41d1641aaa-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-shared-cryptographic-resources.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Shared Cryptographic Resources + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. SHOULD: Shared cryptographic resources (RSA_POOL) SHOULD be modeled as centralized singletons or pools to avoid redundant key generation overhead + +## Policy Block + +- SHOULD Shared cryptographic resources (RSA_POOL) SHOULD be modeled as centralized singletons or pools to avoid redundant key generation overhead + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/171a2ff9-448e-44ad-aea6-5b5acdfde617-standardize-authorization-policy-configuration-with-named-scopes-authentication-scheme-configuration.md b/docs/adr/171a2ff9-448e-44ad-aea6-5b5acdfde617-standardize-authorization-policy-configuration-with-named-scopes-authentication-scheme-configuration.md new file mode 100644 index 000000000000..aebd0c696da0 --- /dev/null +++ b/docs/adr/171a2ff9-448e-44ad-aea6-5b5acdfde617-standardize-authorization-policy-configuration-with-named-scopes-authentication-scheme-configuration.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authentication Scheme Configuration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. MUST: Authentication scheme configuration MUST precede authorization policy configuration in the service registration pipeline + +## Policy Block + +- MUST Authentication scheme configuration MUST precede authorization policy configuration in the service registration pipeline + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/175e5898-be14-42bf-af34-1bbf3b90ece2-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md b/docs/adr/175e5898-be14-42bf-af34-1bbf3b90ece2-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md new file mode 100644 index 000000000000..3401fad635e1 --- /dev/null +++ b/docs/adr/175e5898-be14-42bf-af34-1bbf3b90ece2-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Service Registration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. MUST: Cache service registration MUST use ExtendedCacheServiceCollectionExtensions.AddExtendedCache as the public API contract + +## Policy Block + +- MUST Cache service registration MUST use ExtendedCacheServiceCollectionExtensions.AddExtendedCache as the public API contract + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/17646b12-9b44-429d-8cda-26504ef06142-adopt-api-key-authentication-scheme-for-scim-service-endpoints-integration-test-factories.md b/docs/adr/17646b12-9b44-429d-8cda-26504ef06142-adopt-api-key-authentication-scheme-for-scim-service-endpoints-integration-test-factories.md new file mode 100644 index 000000000000..31341cf543b4 --- /dev/null +++ b/docs/adr/17646b12-9b44-429d-8cda-26504ef06142-adopt-api-key-authentication-scheme-for-scim-service-endpoints-integration-test-factories.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Integration Test Factories + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. MAY: Integration test factories MAY override production authentication with test-specific handlers that bypass credential validation for controlled test environments + +## Policy Block + +- MAY Integration test factories MAY override production authentication with test-specific handlers that bypass credential validation for controlled test environments + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/19153cc8-fd17-4cdd-b627-3b7a111b4fe4-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-separate-read.md b/docs/adr/19153cc8-fd17-4cdd-b627-3b7a111b4fe4-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-separate-read.md new file mode 100644 index 000000000000..ad3241f00e43 --- /dev/null +++ b/docs/adr/19153cc8-fd17-4cdd-b627-3b7a111b4fe4-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-separate-read.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Separate Read + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. SHOULD: Controllers SHOULD separate read-only collection access from editable collection access when merging user permissions to preserve collections the current user cannot modify + +## Policy Block + +- SHOULD Controllers SHOULD separate read-only collection access from editable collection access when merging user permissions to preserve collections the current user cannot modify + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/1a263ad8-362a-4bed-8d4c-ff152c9ea4f0-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-validating-successful.md b/docs/adr/1a263ad8-362a-4bed-8d4c-ff152c9ea4f0-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-validating-successful.md new file mode 100644 index 000000000000..552b8ce5e0be --- /dev/null +++ b/docs/adr/1a263ad8-362a-4bed-8d4c-ff152c9ea4f0-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-validating-successful.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Validating Successful + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. SHOULD: Tests validating successful authentication SHOULD assert on critical security properties including KDF type, KDF iterations, and encrypted key material + +## Policy Block + +- SHOULD Tests validating successful authentication SHOULD assert on critical security properties including KDF type, KDF iterations, and encrypted key material + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/1a73e7c0-65d3-440c-b1eb-3c8d3997c31f-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-combine-declarative.md b/docs/adr/1a73e7c0-65d3-440c-b1eb-3c8d3997c31f-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-combine-declarative.md new file mode 100644 index 000000000000..f46b1496689a --- /dev/null +++ b/docs/adr/1a73e7c0-65d3-440c-b1eb-3c8d3997c31f-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-combine-declarative.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Combine Declarative + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. MAY: Controllers MAY combine declarative Authorize attributes with imperative IAuthorizationService calls for layered authorization + +## Policy Block + +- MAY Controllers MAY combine declarative Authorize attributes with imperative IAuthorizationService calls for layered authorization + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/1aa263f5-bb5a-4c72-9391-5470aed03a1c-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controller-actions-not.md b/docs/adr/1aa263f5-bb5a-4c72-9391-5470aed03a1c-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controller-actions-not.md new file mode 100644 index 000000000000..7950c095c24e --- /dev/null +++ b/docs/adr/1aa263f5-bb5a-4c72-9391-5470aed03a1c-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controller-actions-not.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Controller Actions Not + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. MUST_NOT: Controller actions MUST NOT implement authorization logic imperatively within the action method body; authorization decisions MUST be externalized to authorization handlers + +## Policy Block + +- MUST_NOT Controller actions MUST NOT implement authorization logic imperatively within the action method body; authorization decisions MUST be externalized to authorization handlers + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/1acafa6d-8d2f-49da-8c36-0b8c136c602f-use-system-text-json-for-scim-api-data-access-serialization-data-access-operations.md b/docs/adr/1acafa6d-8d2f-49da-8c36-0b8c136c602f-use-system-text-json-for-scim-api-data-access-serialization-data-access-operations.md new file mode 100644 index 000000000000..88a091062cd6 --- /dev/null +++ b/docs/adr/1acafa6d-8d2f-49da-8c36-0b8c136c602f-use-system-text-json-for-scim-api-data-access-serialization-data-access-operations.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Data Access Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. MUST: Data access operations MUST call DatabaseContext.SaveChanges() to persist SCIM resource modifications + +## Policy Block + +- MUST Data access operations MUST call DatabaseContext.SaveChanges() to persist SCIM resource modifications + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/1b71f2d5-afd2-4ba4-8a75-16c87a1823dc-adopt-attribute-based-authorization-model-for-controller-actions-controllers-use-authorize.md b/docs/adr/1b71f2d5-afd2-4ba4-8a75-16c87a1823dc-adopt-attribute-based-authorization-model-for-controller-actions-controllers-use-authorize.md new file mode 100644 index 000000000000..66184e13754b --- /dev/null +++ b/docs/adr/1b71f2d5-afd2-4ba4-8a75-16c87a1823dc-adopt-attribute-based-authorization-model-for-controller-actions-controllers-use-authorize.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Controllers Use Authorize + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. SHOULD: Controllers SHOULD use [Authorize("Application")] at the class level for base authentication requirements, with action-specific attributes for fine-grained authorization + +## Policy Block + +- SHOULD Controllers SHOULD use [Authorize("Application")] at the class level for base authentication requirements, with action-specific attributes for fine-grained authorization + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/1cc0b477-2d8d-47e4-a0b8-8cc86275aaf1-establish-http-client-boundaries-for-external-service-integration-services-register-multiple.md b/docs/adr/1cc0b477-2d8d-47e4-a0b8-8cc86275aaf1-establish-http-client-boundaries-for-external-service-integration-services-register-multiple.md new file mode 100644 index 000000000000..c2e34e743be5 --- /dev/null +++ b/docs/adr/1cc0b477-2d8d-47e4-a0b8-8cc86275aaf1-establish-http-client-boundaries-for-external-service-integration-services-register-multiple.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: Services Register Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. MAY: Services MAY register multiple named HTTP clients with different configurations for different external service endpoints + +## Policy Block + +- MAY Services MAY register multiple named HTTP clients with different configurations for different external service endpoints + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/1f053f1e-a6ad-4c43-a3dc-e069331b9ca5-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-additional-authorization-checks.md b/docs/adr/1f053f1e-a6ad-4c43-a3dc-e069331b9ca5-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-additional-authorization-checks.md new file mode 100644 index 000000000000..9a714d5885ab --- /dev/null +++ b/docs/adr/1f053f1e-a6ad-4c43-a3dc-e069331b9ca5-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-additional-authorization-checks.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Additional Authorization Checks + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. MAY: Additional authorization checks using ICurrentContext MAY be performed within endpoint methods for complex authorization logic that cannot be expressed declaratively + +## Policy Block + +- MAY Additional authorization checks using ICurrentContext MAY be performed within endpoint methods for complex authorization logic that cannot be expressed declaratively + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/1f6f7f84-717f-498e-b845-592fe052e6d8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-functions-use.md b/docs/adr/1f6f7f84-717f-498e-b845-592fe052e6d8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-functions-use.md new file mode 100644 index 000000000000..0b4b6e1833ab --- /dev/null +++ b/docs/adr/1f6f7f84-717f-498e-b845-592fe052e6d8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-ffi-functions-use.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Ffi Functions Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. SHOULD: FFI functions SHOULD use null pointer checks and return error codes rather than panicking on invalid input + +## Policy Block + +- SHOULD FFI functions SHOULD use null pointer checks and return error codes rather than panicking on invalid input + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/205a829c-f4e2-45ae-9b0a-5ccbb7494a9b-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-cstr-string-conversions.md b/docs/adr/205a829c-f4e2-45ae-9b0a-5ccbb7494a9b-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-cstr-string-conversions.md new file mode 100644 index 000000000000..c6763f69f12e --- /dev/null +++ b/docs/adr/205a829c-f4e2-45ae-9b0a-5ccbb7494a9b-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-cstr-string-conversions.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Cstr String Conversions + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. MUST: CStr to String conversions MUST handle UTF-8 validation errors explicitly and return appropriate error codes to C callers + +## Policy Block + +- MUST CStr to String conversions MUST handle UTF-8 validation errors explicitly and return appropriate error codes to C callers + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/2156771a-e379-4878-b99f-176aad22109b-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-use-allowanonymous.md b/docs/adr/2156771a-e379-4878-b99f-176aad22109b-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-use-allowanonymous.md new file mode 100644 index 000000000000..adb29a23178a --- /dev/null +++ b/docs/adr/2156771a-e379-4878-b99f-176aad22109b-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-use-allowanonymous.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controllers Use Allowanonymous + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. SHOULD: Controllers SHOULD use AllowAnonymous attribute explicitly for public endpoints to document intentional lack of authorization + +## Policy Block + +- SHOULD Controllers SHOULD use AllowAnonymous attribute explicitly for public endpoints to document intentional lack of authorization + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/218891f7-9da8-4417-a739-5140c3f11a36-enforce-authorization-service-pattern-for-access-control-decisions-protected-controller-actions.md b/docs/adr/218891f7-9da8-4417-a739-5140c3f11a36-enforce-authorization-service-pattern-for-access-control-decisions-protected-controller-actions.md new file mode 100644 index 000000000000..63278b6a1b56 --- /dev/null +++ b/docs/adr/218891f7-9da8-4417-a739-5140c3f11a36-enforce-authorization-service-pattern-for-access-control-decisions-protected-controller-actions.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Protected Controller Actions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MUST: All protected API controller actions MUST use IAuthorizationService.AuthorizeAsync() to enforce authorization decisions before performing operations on protected resources + +## Policy Block + +- MUST All protected API controller actions MUST use IAuthorizationService.AuthorizeAsync() to enforce authorization decisions before performing operations on protected resources + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/229cd360-3e71-4202-a291-9c178aaed87e-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md b/docs/adr/229cd360-3e71-4202-a291-9c178aaed87e-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md new file mode 100644 index 000000000000..5ae6bb0922c7 --- /dev/null +++ b/docs/adr/229cd360-3e71-4202-a291-9c178aaed87e-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. MUST: Fake RSA key constants MUST be prefixed with _FAKE_RSA_KEY_ or similar naming convention to clearly distinguish test fixtures from production key material + +## Policy Block + +- MUST Fake RSA key constants MUST be prefixed with _FAKE_RSA_KEY_ or similar naming convention to clearly distinguish test fixtures from production key material + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/2368cf82-a8ac-4c40-a698-2eb3e6e5c486-adopt-attribute-based-authorization-model-for-controller-actions-authorization-requirement-classes.md b/docs/adr/2368cf82-a8ac-4c40-a698-2eb3e6e5c486-adopt-attribute-based-authorization-model-for-controller-actions-authorization-requirement-classes.md new file mode 100644 index 000000000000..34489b0c6559 --- /dev/null +++ b/docs/adr/2368cf82-a8ac-4c40-a698-2eb3e6e5c486-adopt-attribute-based-authorization-model-for-controller-actions-authorization-requirement-classes.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Requirement Classes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. SHOULD: Authorization requirement classes SHOULD be organized in dedicated Authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) for discoverability + +## Policy Block + +- SHOULD Authorization requirement classes SHOULD be organized in dedicated Authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) for discoverability + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/23bdf879-b4fe-4d4a-bdde-45ddc7890b0b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-wrappers.md b/docs/adr/23bdf879-b4fe-4d4a-bdde-45ddc7890b0b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-wrappers.md new file mode 100644 index 000000000000..6acc341eb7a0 --- /dev/null +++ b/docs/adr/23bdf879-b4fe-4d4a-bdde-45ddc7890b0b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-wrappers.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Custom Result Wrappers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. SHOULD: Custom result wrappers SHOULD validate inner result instances using ArgumentNullException.ThrowIfNull + +## Policy Block + +- SHOULD Custom result wrappers SHOULD validate inner result instances using ArgumentNullException.ThrowIfNull + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/2471eb0e-c976-49b7-9c1b-8d163631e101-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md b/docs/adr/2471eb0e-c976-49b7-9c1b-8d163631e101-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md new file mode 100644 index 000000000000..ea8b3bf41eb5 --- /dev/null +++ b/docs/adr/2471eb0e-c976-49b7-9c1b-8d163631e101-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Fake Rsa Key + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. MUST: All _FAKE_RSA_KEY_* constants MUST contain PEM-encoded PKCS#8 format private keys with BEGIN PRIVATE KEY and END PRIVATE KEY delimiters. + +## Policy Block + +- MUST All _FAKE_RSA_KEY_* constants MUST contain PEM-encoded PKCS#8 format private keys with BEGIN PRIVATE KEY and END PRIVATE KEY delimiters. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/25e3448a-34bf-4fa3-bbdb-5cfa75a9a738-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controllers-managing-related.md b/docs/adr/25e3448a-34bf-4fa3-bbdb-5cfa75a9a738-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controllers-managing-related.md new file mode 100644 index 000000000000..c391024bf7e5 --- /dev/null +++ b/docs/adr/25e3448a-34bf-4fa3-bbdb-5cfa75a9a738-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-controllers-managing-related.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Controllers Managing Related + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. SHOULD: Controllers managing related resources SHOULD apply consistent authorization requirements across all CRUD operations (GET, POST, PUT, DELETE) for that resource type + +## Policy Block + +- SHOULD Controllers managing related resources SHOULD apply consistent authorization requirements across all CRUD operations (GET, POST, PUT, DELETE) for that resource type + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/27694fe9-9e4c-49dc-9467-1a147b3a864e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md b/docs/adr/27694fe9-9e4c-49dc-9467-1a147b3a864e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md new file mode 100644 index 000000000000..e496aed747ea --- /dev/null +++ b/docs/adr/27694fe9-9e4c-49dc-9467-1a147b3a864e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-push-notification-services.md @@ -0,0 +1,116 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Push Notification Services + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The push notification service (IPushNotificationService) processes notifications from multiple domain entities including AdminConsole, Auth, and NotificationCenter modules within the Bit.Core namespace +- Invalid notification states (invalid notification ID and invalid notification status ID) are encountered during runtime processing and require observable quality gates +- The codebase uses structured logging with ILogger to record warning-level events when validation failures occur during push notification processing +- A pragma warning disable directive (B) is present, indicating intentional suppression of specific compiler or analyzer warnings in this quality-critical path + +## Problem Statement + +Push notification services must detect and record invalid notification states (malformed IDs or invalid status values) at runtime to enable operational visibility, debugging, and quality assurance, while balancing the need to suppress specific static analysis warnings that may conflict with the chosen logging strategy. + +## Decision + +1. MUST: Push notification services MUST log warning-level events when encountering invalid notification status IDs using structured logging with the notification ID as a parameter + +## Policy Block + +- MUST Push notification services MUST log warning-level events when encountering invalid notification status IDs using structured logging with the notification ID as a parameter + +In scope: +- All implementations of IPushNotificationService interface +- Push notification processing logic handling Bit.Core.NotificationCenter.Entities +- Validation logic for notification IDs and status IDs +- Runtime quality gates for notification state verification + +Out of scope: +- Logging for successful notification processing (use Info or Debug levels) +- Error-level logging for system failures or exceptions +- Validation logic in non-push notification contexts +- Static analysis warning suppression for non-quality-gate purposes + +Exceptions: +- EXC-001: High-frequency notification processing paths where warning-level logging would create excessive log volume + +## Rationale + +- The evidence shows consistent use of ILogger.LogWarning with structured parameters for two distinct invalid notification scenarios, establishing a quality gate pattern for runtime validation +- Push notifications cross multiple domain boundaries (AdminConsole, Auth, NotificationCenter entities), requiring observable validation points to trace failures across module boundaries +- Warning-level logging provides operational visibility without triggering error alerting, appropriate for validation failures that may be recoverable or expected in certain edge cases +- The presence of pragma warning disable B indicates intentional acceptance of static analysis warnings in favor of the runtime observability pattern + +## Consequences + +Positive: +- Operational teams gain visibility into invalid notification states without manual debugging or code instrumentation +- Structured logging with notification IDs enables correlation of validation failures with specific notification instances across distributed logs +- Consistent warning-level logging establishes a quality gate that can be monitored, alerted on, and analyzed for trends +- Cross-module validation failures become observable at the push service boundary, simplifying root cause analysis + +Negative: +- Warning-level logs may accumulate in high-volume notification scenarios, increasing log storage costs and noise +- Suppression of static analysis warnings (pragma disable) reduces compile-time safety checks and may mask related code quality issues +- Developers must maintain discipline to use structured logging templates rather than simpler string concatenation +- The pattern creates a dependency on logging infrastructure availability for quality gate observability + +## Alternatives + +- Use exception throwing for invalid notification states instead of warning-level logging (rejected) + Rejected because: Exceptions would disrupt notification processing flow and trigger error-level alerting for potentially recoverable validation failures, creating operational noise + When valid: When invalid notification states represent unrecoverable errors that should halt processing +- Implement metrics-based counters for invalid notifications without detailed logging (rejected) + Rejected because: Metrics alone lack the contextual detail (specific notification IDs) needed for debugging individual validation failures + When valid: As a complementary approach for high-level trend monitoring alongside detailed logging +- Use Debug-level logging for validation failures (rejected) + Rejected because: Debug-level logs are typically disabled in production, eliminating operational visibility into validation failures + When valid: In development or staging environments where verbose logging is acceptable + +## Risks + +- High-frequency invalid notifications could generate excessive log volume, impacting log infrastructure performance and costs + Mitigation: Implement log sampling or rate limiting for validation warnings if frequency exceeds operational thresholds; monitor log volume metrics + Owner: Platform engineering team +- Pragma warning suppression may mask legitimate code quality issues flagged by static analysis + Mitigation: Document specific warning codes being suppressed; periodically review suppressed warnings to ensure they remain justified + Owner: Code quality team +- Inconsistent application of logging pattern across different notification entity types could create observability gaps + Mitigation: Implement automated verification (linting or testing) to ensure all notification validation paths include structured warning logs + Owner: Engineering team + +## Implementation Notes + +- Use ILogger interface with structured logging templates: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id) +- Apply the pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities +- Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern +- Consider implementing log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform + +## Continuation Context + + +Verify commands: +- grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' +- grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' +- find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; + +Accept when: +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate + +## Enforcement + +- Verified by: Code review checklist requiring structured warning logs for all notification validation failures +- Verified by: Automated grep-based verification in CI pipeline checking for LogWarning patterns in push notification services +- Verified by: Static analysis configuration review to ensure pragma warning suppressions are documented +- Violation handling: Code review rejection if validation failures lack warning-level logging with structured parameters +- Violation handling: CI pipeline warnings if push notification services are modified without corresponding logging verification +- Violation handling: Quarterly audit of pragma warning suppressions to ensure they remain justified and documented +- Exception process: Submit exception request to platform architecture team with performance impact analysis for high-frequency paths +- Exception process: Provide alternative observability mechanism (metrics, sampling strategy) in exception request +- Exception process: Document approved exceptions in service-level README with rationale and compensating controls \ No newline at end of file diff --git a/docs/adr/27695c88-64e9-48cb-94cb-0759a0ba7b96-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-checks-execute.md b/docs/adr/27695c88-64e9-48cb-94cb-0759a0ba7b96-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-checks-execute.md new file mode 100644 index 000000000000..a1069289a446 --- /dev/null +++ b/docs/adr/27695c88-64e9-48cb-94cb-0759a0ba7b96-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-checks-execute.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Authorization Checks Execute + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. MUST: Authorization checks MUST execute before domain validation logic in all organization user management endpoints + +## Policy Block + +- MUST Authorization checks MUST execute before domain validation logic in all organization user management endpoints + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/29556473-2e70-4ba2-aea9-40b4dd4a120c-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-cross-language-data.md b/docs/adr/29556473-2e70-4ba2-aea9-40b4dd4a120c-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-cross-language-data.md new file mode 100644 index 000000000000..8383886b3de0 --- /dev/null +++ b/docs/adr/29556473-2e70-4ba2-aea9-40b4dd4a120c-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-cross-language-data.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Cross Language Data + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. SHOULD: Cross-language data structures (e.g., Rust FFI bindings) SHOULD use explicit type declarations with standard library types (std::ffi::CString, std::collections::HashSet) for interoperability + +## Policy Block + +- SHOULD Cross-language data structures (e.g., Rust FFI bindings) SHOULD use explicit type declarations with standard library types (std::ffi::CString, std::collections::HashSet) for interoperability + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/2b775808-03a5-4387-84e4-0cb3a0b2162a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md b/docs/adr/2b775808-03a5-4387-84e4-0cb3a0b2162a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md new file mode 100644 index 000000000000..9e218f3d8c37 --- /dev/null +++ b/docs/adr/2b775808-03a5-4387-84e4-0cb3a0b2162a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Accepting + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. MUST: All FFI functions accepting C string pointers (c_char) MUST convert them to CStr using CStr::from_ptr before dereferencing or using the string data + +## Policy Block + +- MUST All FFI functions accepting C string pointers (c_char) MUST convert them to CStr using CStr::from_ptr before dereferencing or using the string data + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/2daa6496-ac17-4ea7-a429-ab8b08960dc9-enforce-authorization-attributes-on-api-controllers-via-unit-tests-authorization-verification-tests.md b/docs/adr/2daa6496-ac17-4ea7-a429-ab8b08960dc9-enforce-authorization-attributes-on-api-controllers-via-unit-tests-authorization-verification-tests.md new file mode 100644 index 000000000000..b541b31a4a72 --- /dev/null +++ b/docs/adr/2daa6496-ac17-4ea7-a429-ab8b08960dc9-enforce-authorization-attributes-on-api-controllers-via-unit-tests-authorization-verification-tests.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Authorization Verification Tests + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. MUST: Authorization verification tests MUST throw Xunit.Sdk.FailException with descriptive error messages identifying missing attributes and affected controllers/methods + +## Policy Block + +- MUST Authorization verification tests MUST throw Xunit.Sdk.FailException with descriptive error messages identifying missing attributes and affected controllers/methods + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/2dbcdbcc-a1f8-4732-afa0-68852b3eec23-adopt-http-client-abstraction-for-external-service-integration-http-clients-registered.md b/docs/adr/2dbcdbcc-a1f8-4732-afa0-68852b3eec23-adopt-http-client-abstraction-for-external-service-integration-http-clients-registered.md new file mode 100644 index 000000000000..2d4a25fd408e --- /dev/null +++ b/docs/adr/2dbcdbcc-a1f8-4732-afa0-68852b3eec23-adopt-http-client-abstraction-for-external-service-integration-http-clients-registered.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Http Clients Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. MUST: HTTP clients MUST be registered through dependency injection containers to enable proper lifecycle management and connection pooling + +## Policy Block + +- MUST HTTP clients MUST be registered through dependency injection containers to enable proper lifecycle management and connection pooling + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/2dcfc033-1bdc-4e09-9c4f-fd7199b9e904-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md b/docs/adr/2dcfc033-1bdc-4e09-9c4f-fd7199b9e904-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md new file mode 100644 index 000000000000..d0dcb65eb0e7 --- /dev/null +++ b/docs/adr/2dcfc033-1bdc-4e09-9c4f-fd7199b9e904-expose-extended-cache-configuration-as-public-api-contract-cache-service-registration.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Service Registration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. SHOULD: Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to prevent duplicate registrations + +## Policy Block + +- SHOULD Cache service registration SHOULD use Microsoft.Extensions.DependencyInjection.Extensions.TryAdd methods to prevent duplicate registrations + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/2e078989-f0a0-4944-b666-6028a7c74890-use-structured-logging-with-contextual-parameters-for-external-service-failures-use-logerror-level.md b/docs/adr/2e078989-f0a0-4944-b666-6028a7c74890-use-structured-logging-with-contextual-parameters-for-external-service-failures-use-logerror-level.md new file mode 100644 index 000000000000..46a4115557b0 --- /dev/null +++ b/docs/adr/2e078989-f0a0-4944-b666-6028a7c74890-use-structured-logging-with-contextual-parameters-for-external-service-failures-use-logerror-level.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Use Logerror Level + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. SHOULD: Use LogError level for exceptions that represent operational failures requiring investigation, even if they do not block the user request + +## Policy Block + +- SHOULD Use LogError level for exceptions that represent operational failures requiring investigation, even if they do not block the user request + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/2eaa7b00-5d0f-40bf-b471-3a0993ccac0e-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-test-fixtures-use.md b/docs/adr/2eaa7b00-5d0f-40bf-b471-3a0993ccac0e-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-test-fixtures-use.md new file mode 100644 index 000000000000..d095fd961b2e --- /dev/null +++ b/docs/adr/2eaa7b00-5d0f-40bf-b471-3a0993ccac0e-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-test-fixtures-use.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Test Fixtures Use + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. MAY: Test fixtures MAY use hardcoded string constants (_FAKE_RSA_KEY_*) to validate FFI string handling without requiring external C callers + +## Policy Block + +- MAY Test fixtures MAY use hardcoded string constants (_FAKE_RSA_KEY_*) to validate FFI string handling without requiring external C callers + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/2eb105ee-ef02-4462-9a0f-7284bb1c2b10-use-system-text-json-for-scim-api-data-access-serialization-json-serialization-use.md b/docs/adr/2eb105ee-ef02-4462-9a0f-7284bb1c2b10-use-system-text-json-for-scim-api-data-access-serialization-json-serialization-use.md new file mode 100644 index 000000000000..eb849b27f8bf --- /dev/null +++ b/docs/adr/2eb105ee-ef02-4462-9a0f-7284bb1c2b10-use-system-text-json-for-scim-api-data-access-serialization-json-serialization-use.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Json Serialization Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. MUST: JSON serialization MUST use System.Text.Encodings.Web for proper encoding of special characters in SCIM data + +## Policy Block + +- MUST JSON serialization MUST use System.Text.Encodings.Web for proper encoding of special characters in SCIM data + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/304d2cd5-6451-4c86-a8c1-c6eca4bbcdc7-log-redis-connection-failures-in-distributed-cache-extensions-additional-diagnostic-context.md b/docs/adr/304d2cd5-6451-4c86-a8c1-c6eca4bbcdc7-log-redis-connection-failures-in-distributed-cache-extensions-additional-diagnostic-context.md new file mode 100644 index 000000000000..ced398781f42 --- /dev/null +++ b/docs/adr/304d2cd5-6451-4c86-a8c1-c6eca4bbcdc7-log-redis-connection-failures-in-distributed-cache-extensions-additional-diagnostic-context.md @@ -0,0 +1,100 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Additional Diagnostic Context + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses StackExchangeRedis as a distributed cache implementation via Microsoft.Extensions.Caching.StackExchangeRedis +- Redis connection establishment occurs in ExtendedCacheServiceCollectionExtensions during service registration, requiring error visibility for operational diagnostics +- The pattern appears in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs where ConnectionMultiplexer.Connect operations are wrapped with structured logging +- Cache initialization failures must be observable to distinguish between configuration errors, network issues, and Redis availability problems + +## Problem Statement + +When Redis connection failures occur during distributed cache initialization, operators and developers need structured, contextual error information to diagnose whether the failure stems from misconfiguration, network connectivity, or Redis service availability, without relying on unhandled exceptions or silent failures. + +## Decision + +1. MAY: Additional diagnostic context such as connection string (sanitized) or retry attempts MAY be included in error logs + +## Policy Block + +- MAY Additional diagnostic context such as connection string (sanitized) or retry attempts MAY be included in error logs + +## Rationale + +- The evidence shows explicit error logging with logger?.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) in ExtendedCacheServiceCollectionExtensions.cs, establishing a pattern of structured error reporting +- Redis connection failures are critical operational events that require immediate visibility, as they directly impact application caching capabilities and performance +- Structured logging with cache name context enables filtering and alerting on specific cache instances in multi-cache deployments +- The pattern uses Microsoft.Extensions.Logging abstractions, ensuring compatibility with various logging providers and observability platforms + +## Consequences + +Positive: +- Operators gain immediate visibility into Redis connection failures through structured logs with contextual information +- Diagnostic time is reduced by including cache name and exception details in a single log entry +- Structured logging parameters enable automated alerting and filtering in log aggregation systems +- The pattern integrates with existing Microsoft.Extensions.Logging infrastructure without additional dependencies + +Negative: +- Log volume increases during Redis outages or misconfigurations, potentially impacting log storage costs +- Sensitive connection string information must be carefully sanitized to avoid credential leakage in logs +- The null-conditional operator (logger?) allows silent failures if logging is not configured, reducing error visibility + +## Alternatives + +- Allow ConnectionMultiplexer.Connect exceptions to propagate unhandled, relying on global exception handlers (rejected) + Rejected because: Unhandled exceptions during service registration cause application startup failures without contextual information about which cache failed or why + When valid: In scenarios where fail-fast behavior is required and any cache initialization failure should prevent application startup +- Use health checks to detect Redis connectivity issues post-startup rather than logging during initialization (rejected) + Rejected because: Health checks provide runtime monitoring but do not capture initialization-time failures or provide immediate diagnostic context during startup + When valid: As a complementary approach for ongoing runtime monitoring after successful initialization +- Implement retry logic with exponential backoff before logging connection failures (deferred) + Rejected because: Retry logic adds complexity and startup latency; the current pattern focuses on observability rather than resilience + When valid: When transient network issues are common and automatic recovery is preferred over immediate failure reporting + +## Risks + +- Connection string credentials may be inadvertently logged if error messages include full connection details + Mitigation: Sanitize connection strings before logging and rely on structured parameters that exclude sensitive data + Owner: engineering team +- The null-conditional operator (logger?) allows silent failures when ILogger is not injected or configured + Mitigation: Ensure logging infrastructure is configured before cache service registration or use non-null logger instances + Owner: engineering team +- High-frequency connection failures during Redis outages may generate excessive log volume + Mitigation: Implement log rate limiting or circuit breaker patterns for repeated connection attempts + Owner: operations team + +## Implementation Notes + +- Wrap ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions +- Use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) +- Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns +- Consider adding correlation IDs or request context to error logs for distributed tracing integration + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*Failed to connect to Redis' src/ +- grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' +- dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +Accept when: +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + +## Enforcement + +- Verified by: Code review checklist requiring error logging for all external service connections +- Verified by: Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks +- Verified by: Integration tests that simulate Redis connection failures and assert expected log output +- Violation handling: Pull requests introducing cache initialization code without error logging are flagged during code review +- Violation handling: Static analysis warnings are treated as build failures in CI pipeline +- Violation handling: Production incidents involving unlogged cache failures trigger retrospective reviews and pattern reinforcement +- Exception process: Exceptions require architectural review approval with documented justification +- Exception process: Alternative observability mechanisms (e.g., metrics, tracing) must be demonstrated +- Exception process: Exception approvals are time-limited and require renewal during annual architecture reviews \ No newline at end of file diff --git a/docs/adr/30b72ec9-4f3f-4f1c-8352-06631ef7b00f-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-use.md b/docs/adr/30b72ec9-4f3f-4f1c-8352-06631ef7b00f-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-use.md new file mode 100644 index 000000000000..0ec07c3bba89 --- /dev/null +++ b/docs/adr/30b72ec9-4f3f-4f1c-8352-06631ef7b00f-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-use.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Code Use + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. MAY: Test code MAY use std::ffi types (c_char, CStr, CString) to validate FFI boundaries with embedded key material + +## Policy Block + +- MAY Test code MAY use std::ffi types (c_char, CStr, CString) to validate FFI boundaries with embedded key material + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/3121bce3-ebbb-40ed-92ef-7b413ac61c13-enforce-authorization-via-policy-based-configuration-in-scim-services-production-scim-policies.md b/docs/adr/3121bce3-ebbb-40ed-92ef-7b413ac61c13-enforce-authorization-via-policy-based-configuration-in-scim-services-production-scim-policies.md new file mode 100644 index 000000000000..1cc66fdee530 --- /dev/null +++ b/docs/adr/3121bce3-ebbb-40ed-92ef-7b413ac61c13-enforce-authorization-via-policy-based-configuration-in-scim-services-production-scim-policies.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Production Scim Policies + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. MUST: Production SCIM policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') + +## Policy Block + +- MUST Production SCIM policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/32ec4bdf-3e54-40c5-924a-208e17fbd125-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-input-validation-ffi.md b/docs/adr/32ec4bdf-3e54-40c5-924a-208e17fbd125-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-input-validation-ffi.md new file mode 100644 index 000000000000..fff802da2537 --- /dev/null +++ b/docs/adr/32ec4bdf-3e54-40c5-924a-208e17fbd125-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-input-validation-ffi.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Input Validation Ffi + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. MUST: Input validation at FFI boundaries MUST occur before any cryptographic operations (cipher generation, RSA key operations, SymmetricCryptoKey usage) + +## Policy Block + +- MUST Input validation at FFI boundaries MUST occur before any cryptographic operations (cipher generation, RSA key operations, SymmetricCryptoKey usage) + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/3351ba53-1850-4f4d-ad66-4c82146e896a-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md b/docs/adr/3351ba53-1850-4f4d-ad66-4c82146e896a-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md new file mode 100644 index 000000000000..18d866e18b68 --- /dev/null +++ b/docs/adr/3351ba53-1850-4f4d-ad66-4c82146e896a-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controller Action Methods + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. MUST_NOT: Controller action methods MUST NOT implement authorization logic imperatively within method bodies when declarative attribute-based authorization can express the requirement + +## Policy Block + +- MUST_NOT Controller action methods MUST NOT implement authorization logic imperatively within method bodies when declarative attribute-based authorization can express the requirement + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/335364a7-51cc-460c-94b0-ceb75ebe48f8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-string-data-crossing.md b/docs/adr/335364a7-51cc-460c-94b0-ceb75ebe48f8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-string-data-crossing.md new file mode 100644 index 000000000000..326a459d1a03 --- /dev/null +++ b/docs/adr/335364a7-51cc-460c-94b0-ceb75ebe48f8-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-string-data-crossing.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: String Data Crossing + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. MUST: All string data crossing the FFI boundary MUST use std::ffi::CString for Rust-to-C transfers and std::ffi::CStr for C-to-Rust transfers + +## Policy Block + +- MUST All string data crossing the FFI boundary MUST use std::ffi::CString for Rust-to-C transfers and std::ffi::CStr for C-to-Rust transfers + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/358e360f-ab17-4202-b212-3da0c0c3dc5d-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-protected-controller-actions.md b/docs/adr/358e360f-ab17-4202-b212-3da0c0c3dc5d-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-protected-controller-actions.md new file mode 100644 index 000000000000..4e7238b508a2 --- /dev/null +++ b/docs/adr/358e360f-ab17-4202-b212-3da0c0c3dc5d-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-protected-controller-actions.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Protected Controller Actions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. MUST: All protected API controller actions MUST use the [Authorize] attribute with a generic type parameter specifying a custom requirement class that implements IAuthorizationRequirement + +## Policy Block + +- MUST All protected API controller actions MUST use the [Authorize] attribute with a generic type parameter specifying a custom requirement class that implements IAuthorizationRequirement + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/38530c47-f864-481a-9c77-d612e8841263-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-authorize-attributes.md b/docs/adr/38530c47-f864-481a-9c77-d612e8841263-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-authorize-attributes.md new file mode 100644 index 000000000000..94353f2d3c4f --- /dev/null +++ b/docs/adr/38530c47-f864-481a-9c77-d612e8841263-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-authorize-attributes.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Authorize Attributes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. MUST: Controllers with [Authorize] attributes or custom authorization requirements MUST inject ILogger and use structured logging for all exception paths within authorized actions + +## Policy Block + +- MUST Controllers with [Authorize] attributes or custom authorization requirements MUST inject ILogger and use structured logging for all exception paths within authorized actions + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/385fbeac-2009-4964-97f0-f639567e8c51-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-service-controllers-separate.md b/docs/adr/385fbeac-2009-4964-97f0-f639567e8c51-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-service-controllers-separate.md new file mode 100644 index 000000000000..7fc2a0ddcc2e --- /dev/null +++ b/docs/adr/385fbeac-2009-4964-97f0-f639567e8c51-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-service-controllers-separate.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Service Controllers Separate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. MUST: Service API controllers MUST separate command operations from query operations using dedicated interface abstractions (e.g., ISceneExecutor, IDestroySceneCommand, IQueries) + +## Policy Block + +- MUST Service API controllers MUST separate command operations from query operations using dedicated interface abstractions (e.g., ISceneExecutor, IDestroySceneCommand, IQueries) + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/39443d4c-df3a-4eb5-87de-4a7f1c7d774a-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-scim-endpoint-tests.md b/docs/adr/39443d4c-df3a-4eb5-87de-4a7f1c7d774a-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-scim-endpoint-tests.md new file mode 100644 index 000000000000..aba20caef878 --- /dev/null +++ b/docs/adr/39443d4c-df3a-4eb5-87de-4a7f1c7d774a-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-scim-endpoint-tests.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Scim Endpoint Tests + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. MUST: SCIM endpoint tests MUST use async HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) with await for coordinated database access + +## Policy Block + +- MUST SCIM endpoint tests MUST use async HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) with await for coordinated database access + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/3a5da651-71a4-4609-ac03-ac704880f5b9-log-redis-connection-failures-in-distributed-cache-extensions-logging-statements-use.md b/docs/adr/3a5da651-71a4-4609-ac03-ac704880f5b9-log-redis-connection-failures-in-distributed-cache-extensions-logging-statements-use.md new file mode 100644 index 000000000000..b600c63dc62e --- /dev/null +++ b/docs/adr/3a5da651-71a4-4609-ac03-ac704880f5b9-log-redis-connection-failures-in-distributed-cache-extensions-logging-statements-use.md @@ -0,0 +1,100 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Logging Statements Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses StackExchangeRedis as a distributed cache implementation via Microsoft.Extensions.Caching.StackExchangeRedis +- Redis connection establishment occurs in ExtendedCacheServiceCollectionExtensions during service registration, requiring error visibility for operational diagnostics +- The pattern appears in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs where ConnectionMultiplexer.Connect operations are wrapped with structured logging +- Cache initialization failures must be observable to distinguish between configuration errors, network issues, and Redis availability problems + +## Problem Statement + +When Redis connection failures occur during distributed cache initialization, operators and developers need structured, contextual error information to diagnose whether the failure stems from misconfiguration, network connectivity, or Redis service availability, without relying on unhandled exceptions or silent failures. + +## Decision + +1. SHOULD: Logging statements SHOULD use structured logging syntax with named parameters rather than string interpolation + +## Policy Block + +- SHOULD Logging statements SHOULD use structured logging syntax with named parameters rather than string interpolation + +## Rationale + +- The evidence shows explicit error logging with logger?.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) in ExtendedCacheServiceCollectionExtensions.cs, establishing a pattern of structured error reporting +- Redis connection failures are critical operational events that require immediate visibility, as they directly impact application caching capabilities and performance +- Structured logging with cache name context enables filtering and alerting on specific cache instances in multi-cache deployments +- The pattern uses Microsoft.Extensions.Logging abstractions, ensuring compatibility with various logging providers and observability platforms + +## Consequences + +Positive: +- Operators gain immediate visibility into Redis connection failures through structured logs with contextual information +- Diagnostic time is reduced by including cache name and exception details in a single log entry +- Structured logging parameters enable automated alerting and filtering in log aggregation systems +- The pattern integrates with existing Microsoft.Extensions.Logging infrastructure without additional dependencies + +Negative: +- Log volume increases during Redis outages or misconfigurations, potentially impacting log storage costs +- Sensitive connection string information must be carefully sanitized to avoid credential leakage in logs +- The null-conditional operator (logger?) allows silent failures if logging is not configured, reducing error visibility + +## Alternatives + +- Allow ConnectionMultiplexer.Connect exceptions to propagate unhandled, relying on global exception handlers (rejected) + Rejected because: Unhandled exceptions during service registration cause application startup failures without contextual information about which cache failed or why + When valid: In scenarios where fail-fast behavior is required and any cache initialization failure should prevent application startup +- Use health checks to detect Redis connectivity issues post-startup rather than logging during initialization (rejected) + Rejected because: Health checks provide runtime monitoring but do not capture initialization-time failures or provide immediate diagnostic context during startup + When valid: As a complementary approach for ongoing runtime monitoring after successful initialization +- Implement retry logic with exponential backoff before logging connection failures (deferred) + Rejected because: Retry logic adds complexity and startup latency; the current pattern focuses on observability rather than resilience + When valid: When transient network issues are common and automatic recovery is preferred over immediate failure reporting + +## Risks + +- Connection string credentials may be inadvertently logged if error messages include full connection details + Mitigation: Sanitize connection strings before logging and rely on structured parameters that exclude sensitive data + Owner: engineering team +- The null-conditional operator (logger?) allows silent failures when ILogger is not injected or configured + Mitigation: Ensure logging infrastructure is configured before cache service registration or use non-null logger instances + Owner: engineering team +- High-frequency connection failures during Redis outages may generate excessive log volume + Mitigation: Implement log rate limiting or circuit breaker patterns for repeated connection attempts + Owner: operations team + +## Implementation Notes + +- Wrap ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions +- Use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) +- Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns +- Consider adding correlation IDs or request context to error logs for distributed tracing integration + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*Failed to connect to Redis' src/ +- grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' +- dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +Accept when: +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + +## Enforcement + +- Verified by: Code review checklist requiring error logging for all external service connections +- Verified by: Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks +- Verified by: Integration tests that simulate Redis connection failures and assert expected log output +- Violation handling: Pull requests introducing cache initialization code without error logging are flagged during code review +- Violation handling: Static analysis warnings are treated as build failures in CI pipeline +- Violation handling: Production incidents involving unlogged cache failures trigger retrospective reviews and pattern reinforcement +- Exception process: Exceptions require architectural review approval with documented justification +- Exception process: Alternative observability mechanisms (e.g., metrics, tracing) must be demonstrated +- Exception process: Exception approvals are time-limited and require renewal during annual architecture reviews \ No newline at end of file diff --git a/docs/adr/3c805701-1aa6-4179-a7ab-df1380c5fa57-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-requirements-declared.md b/docs/adr/3c805701-1aa6-4179-a7ab-df1380c5fa57-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-requirements-declared.md new file mode 100644 index 000000000000..45647eb2bc58 --- /dev/null +++ b/docs/adr/3c805701-1aa6-4179-a7ab-df1380c5fa57-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-requirements-declared.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Authorization Requirements Declared + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. MUST: Authorization requirements MUST be declared using ASP.NET Core's attribute-based authorization model at the controller action level + +## Policy Block + +- MUST Authorization requirements MUST be declared using ASP.NET Core's attribute-based authorization model at the controller action level + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/3ddbdebe-6c15-4864-b8f9-d988d0954a44-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-collection-access-modifications.md b/docs/adr/3ddbdebe-6c15-4864-b8f9-d988d0954a44-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-collection-access-modifications.md new file mode 100644 index 000000000000..fde65b11bb56 --- /dev/null +++ b/docs/adr/3ddbdebe-6c15-4864-b8f9-d988d0954a44-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-collection-access-modifications.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Collection Access Modifications + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. MUST: Collection access modifications MUST verify BulkCollectionOperations.ModifyUserAccess authorization for all affected collections before applying changes + +## Policy Block + +- MUST Collection access modifications MUST verify BulkCollectionOperations.ModifyUserAccess authorization for all affected collections before applying changes + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/3f212963-2a7a-4edd-83a7-6faf9f37b6b4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md b/docs/adr/3f212963-2a7a-4edd-83a7-6faf9f37b6b4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md new file mode 100644 index 000000000000..def6e304a7f2 --- /dev/null +++ b/docs/adr/3f212963-2a7a-4edd-83a7-6faf9f37b6b4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. MUST_NOT: Fake RSA keys MUST NOT be used in production code paths or for any real cryptographic security purposes + +## Policy Block + +- MUST_NOT Fake RSA keys MUST NOT be used in production code paths or for any real cryptographic security purposes + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/3f888895-b046-4f11-bc2d-3b22882e76b0-enforce-organization-scoped-authorization-requirements-for-billing-operations-authorization-requirements-billing.md b/docs/adr/3f888895-b046-4f11-bc2d-3b22882e76b0-enforce-organization-scoped-authorization-requirements-for-billing-operations-authorization-requirements-billing.md new file mode 100644 index 000000000000..a38d8f68d59c --- /dev/null +++ b/docs/adr/3f888895-b046-4f11-bc2d-3b22882e76b0-enforce-organization-scoped-authorization-requirements-for-billing-operations-authorization-requirements-billing.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Authorization Requirements Billing + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. SHOULD: Authorization requirements for billing operations SHOULD be defined in dedicated namespaces (Bit.Api.Billing.Models.Requirements) separate from general administrative requirements + +## Policy Block + +- SHOULD Authorization requirements for billing operations SHOULD be defined in dedicated namespaces (Bit.Api.Billing.Models.Requirements) separate from general administrative requirements + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/4249ecc3-367a-40f2-99f8-b23616365041-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-expose.md b/docs/adr/4249ecc3-367a-40f2-99f8-b23616365041-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-expose.md new file mode 100644 index 000000000000..1cf49b418ce6 --- /dev/null +++ b/docs/adr/4249ecc3-367a-40f2-99f8-b23616365041-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-expose.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Result Types Expose + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. MAY: Result types MAY expose strongly-typed Value properties through IValueHttpResult for type-safe response inspection + +## Policy Block + +- MAY Result types MAY expose strongly-typed Value properties through IValueHttpResult for type-safe response inspection + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/4360e829-692d-4f6c-9197-2e9deaa4506e-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-exceptions-external.md b/docs/adr/4360e829-692d-4f6c-9197-2e9deaa4506e-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-exceptions-external.md new file mode 100644 index 000000000000..9d523970f85d --- /dev/null +++ b/docs/adr/4360e829-692d-4f6c-9197-2e9deaa4506e-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-exceptions-external.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Log Exceptions External + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. MUST: Log exceptions from external service calls using ILogger.LogError with the exception object as the first parameter + +## Policy Block + +- MUST Log exceptions from external service calls using ILogger.LogError with the exception object as the first parameter + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/446f3d19-4bdb-4bd7-aa9f-d1e9a2c73445-enforce-organization-scoped-authorization-requirements-for-billing-operations-controllers-bit-billing.md b/docs/adr/446f3d19-4bdb-4bd7-aa9f-d1e9a2c73445-enforce-organization-scoped-authorization-requirements-for-billing-operations-controllers-bit-billing.md new file mode 100644 index 000000000000..0b4fb1292b1f --- /dev/null +++ b/docs/adr/446f3d19-4bdb-4bd7-aa9f-d1e9a2c73445-enforce-organization-scoped-authorization-requirements-for-billing-operations-controllers-bit-billing.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Controllers Bit Billing + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. SHOULD: Controllers in the Bit.Api.Billing.Controllers namespace SHOULD consistently apply the organization-scoped authorization pattern across all billing-related operations + +## Policy Block + +- SHOULD Controllers in the Bit.Api.Billing.Controllers namespace SHOULD consistently apply the organization-scoped authorization pattern across all billing-related operations + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/447141c6-c7e6-48b8-9ea6-daefae21dc4b-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-endpoints-that-allow.md b/docs/adr/447141c6-c7e6-48b8-9ea6-daefae21dc4b-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-endpoints-that-allow.md new file mode 100644 index 000000000000..3f9bd2eab906 --- /dev/null +++ b/docs/adr/447141c6-c7e6-48b8-9ea6-daefae21dc4b-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-endpoints-that-allow.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Endpoints That Allow + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. SHOULD: Endpoints that allow anonymous access SHOULD use the AllowAnonymous attribute explicitly to document the intentional bypass of authorization + +## Policy Block + +- SHOULD Endpoints that allow anonymous access SHOULD use the AllowAnonymous attribute explicitly to document the intentional bypass of authorization + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/44897d9c-1b04-4264-9ce1-6b1a6b4094d8-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-use.md b/docs/adr/44897d9c-1b04-4264-9ce1-6b1a6b4094d8-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-use.md new file mode 100644 index 000000000000..a74fc695d196 --- /dev/null +++ b/docs/adr/44897d9c-1b04-4264-9ce1-6b1a6b4094d8-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-functions-use.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Functions Use + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. MUST: FFI functions MUST use CString::new for outbound string conversions to ensure null-termination and prevent interior null bytes + +## Policy Block + +- MUST FFI functions MUST use CString::new for outbound string conversions to ensure null-termination and prevent interior null bytes + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/44b0e5cd-7f0f-4a32-8d94-965b081e74cf-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-data-access-operations.md b/docs/adr/44b0e5cd-7f0f-4a32-8d94-965b081e74cf-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-data-access-operations.md new file mode 100644 index 000000000000..a3a3a71f8be2 --- /dev/null +++ b/docs/adr/44b0e5cd-7f0f-4a32-8d94-965b081e74cf-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-data-access-operations.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Data Access Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. MUST: All data access operations invoked from API controllers MUST use asynchronous execution patterns with Task-based async/await semantics + +## Policy Block + +- MUST All data access operations invoked from API controllers MUST use asynchronous execution patterns with Task-based async/await semantics + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/459ea228-d332-4b52-a7a4-490be0ffde40-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-implement.md b/docs/adr/459ea228-d332-4b52-a7a4-490be0ffde40-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-implement.md new file mode 100644 index 000000000000..937a9c8eb630 --- /dev/null +++ b/docs/adr/459ea228-d332-4b52-a7a4-490be0ffde40-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-result-types-implement.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Result Types Implement + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. SHOULD: Result types SHOULD implement marker interfaces (IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) to expose metadata without executing the result + +## Policy Block + +- SHOULD Result types SHOULD implement marker interfaces (IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) to expose metadata without executing the result + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/46259ca9-c088-47b1-b31a-417242ff61a0-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-integrate.md b/docs/adr/46259ca9-c088-47b1-b31a-417242ff61a0-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-integrate.md new file mode 100644 index 000000000000..d787c9b2f71b --- /dev/null +++ b/docs/adr/46259ca9-c088-47b1-b31a-417242ff61a0-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-integrate.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Configuration Integrate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. SHOULD: Cache configuration SHOULD integrate with Bit.Core.Settings for connection string and configuration management + +## Policy Block + +- SHOULD Cache configuration SHOULD integrate with Bit.Core.Settings for connection string and configuration management + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/46855cf7-686a-4e5e-9502-81b84d5cf9c5-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-hardcoded-rsa-private.md b/docs/adr/46855cf7-686a-4e5e-9502-81b84d5cf9c5-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-hardcoded-rsa-private.md new file mode 100644 index 000000000000..fe90f0573f97 --- /dev/null +++ b/docs/adr/46855cf7-686a-4e5e-9502-81b84d5cf9c5-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-hardcoded-rsa-private.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Hardcoded Rsa Private + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. MUST: All hardcoded RSA private keys intended for testing MUST use the naming pattern _FAKE_RSA_KEY_N where N is a sequential integer starting from 0. + +## Policy Block + +- MUST All hardcoded RSA private keys intended for testing MUST use the naming pattern _FAKE_RSA_KEY_N where N is a sequential integer starting from 0. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/46a677e4-20f6-494b-a3a7-01251f967dbb-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-combine-multiple.md b/docs/adr/46a677e4-20f6-494b-a3a7-01251f967dbb-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-combine-multiple.md new file mode 100644 index 000000000000..90623f682cd0 --- /dev/null +++ b/docs/adr/46a677e4-20f6-494b-a3a7-01251f967dbb-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-combine-multiple.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Combine Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. MAY: Controllers MAY combine multiple authorization checks by using both attribute-based authorization and programmatic ICurrentContext validation within action methods + +## Policy Block + +- MAY Controllers MAY combine multiple authorization checks by using both attribute-based authorization and programmatic ICurrentContext validation within action methods + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/46c10ab6-e5e1-43e2-9c32-a4ae1256f5db-adopt-attribute-based-authorization-model-for-controller-actions-public-endpoints-that.md b/docs/adr/46c10ab6-e5e1-43e2-9c32-a4ae1256f5db-adopt-attribute-based-authorization-model-for-controller-actions-public-endpoints-that.md new file mode 100644 index 000000000000..fdc4dd4cc260 --- /dev/null +++ b/docs/adr/46c10ab6-e5e1-43e2-9c32-a4ae1256f5db-adopt-attribute-based-authorization-model-for-controller-actions-public-endpoints-that.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Public Endpoints That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. MUST: Public endpoints that bypass authorization MUST explicitly declare [AllowAnonymous] to document the intentional security exception + +## Policy Block + +- MUST Public endpoints that bypass authorization MUST explicitly declare [AllowAnonymous] to document the intentional security exception + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/46f70fba-6b32-4984-a7f2-97fc8f124e81-log-redis-connection-failures-in-distributed-cache-extensions-cache-service-registration.md b/docs/adr/46f70fba-6b32-4984-a7f2-97fc8f124e81-log-redis-connection-failures-in-distributed-cache-extensions-cache-service-registration.md new file mode 100644 index 000000000000..e6e4c8d586db --- /dev/null +++ b/docs/adr/46f70fba-6b32-4984-a7f2-97fc8f124e81-log-redis-connection-failures-in-distributed-cache-extensions-cache-service-registration.md @@ -0,0 +1,100 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Cache Service Registration + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses StackExchangeRedis as a distributed cache implementation via Microsoft.Extensions.Caching.StackExchangeRedis +- Redis connection establishment occurs in ExtendedCacheServiceCollectionExtensions during service registration, requiring error visibility for operational diagnostics +- The pattern appears in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs where ConnectionMultiplexer.Connect operations are wrapped with structured logging +- Cache initialization failures must be observable to distinguish between configuration errors, network issues, and Redis availability problems + +## Problem Statement + +When Redis connection failures occur during distributed cache initialization, operators and developers need structured, contextual error information to diagnose whether the failure stems from misconfiguration, network connectivity, or Redis service availability, without relying on unhandled exceptions or silent failures. + +## Decision + +1. SHOULD: Cache service registration extensions SHOULD wrap ConnectionMultiplexer.Connect calls in try-catch blocks to capture connection exceptions + +## Policy Block + +- SHOULD Cache service registration extensions SHOULD wrap ConnectionMultiplexer.Connect calls in try-catch blocks to capture connection exceptions + +## Rationale + +- The evidence shows explicit error logging with logger?.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) in ExtendedCacheServiceCollectionExtensions.cs, establishing a pattern of structured error reporting +- Redis connection failures are critical operational events that require immediate visibility, as they directly impact application caching capabilities and performance +- Structured logging with cache name context enables filtering and alerting on specific cache instances in multi-cache deployments +- The pattern uses Microsoft.Extensions.Logging abstractions, ensuring compatibility with various logging providers and observability platforms + +## Consequences + +Positive: +- Operators gain immediate visibility into Redis connection failures through structured logs with contextual information +- Diagnostic time is reduced by including cache name and exception details in a single log entry +- Structured logging parameters enable automated alerting and filtering in log aggregation systems +- The pattern integrates with existing Microsoft.Extensions.Logging infrastructure without additional dependencies + +Negative: +- Log volume increases during Redis outages or misconfigurations, potentially impacting log storage costs +- Sensitive connection string information must be carefully sanitized to avoid credential leakage in logs +- The null-conditional operator (logger?) allows silent failures if logging is not configured, reducing error visibility + +## Alternatives + +- Allow ConnectionMultiplexer.Connect exceptions to propagate unhandled, relying on global exception handlers (rejected) + Rejected because: Unhandled exceptions during service registration cause application startup failures without contextual information about which cache failed or why + When valid: In scenarios where fail-fast behavior is required and any cache initialization failure should prevent application startup +- Use health checks to detect Redis connectivity issues post-startup rather than logging during initialization (rejected) + Rejected because: Health checks provide runtime monitoring but do not capture initialization-time failures or provide immediate diagnostic context during startup + When valid: As a complementary approach for ongoing runtime monitoring after successful initialization +- Implement retry logic with exponential backoff before logging connection failures (deferred) + Rejected because: Retry logic adds complexity and startup latency; the current pattern focuses on observability rather than resilience + When valid: When transient network issues are common and automatic recovery is preferred over immediate failure reporting + +## Risks + +- Connection string credentials may be inadvertently logged if error messages include full connection details + Mitigation: Sanitize connection strings before logging and rely on structured parameters that exclude sensitive data + Owner: engineering team +- The null-conditional operator (logger?) allows silent failures when ILogger is not injected or configured + Mitigation: Ensure logging infrastructure is configured before cache service registration or use non-null logger instances + Owner: engineering team +- High-frequency connection failures during Redis outages may generate excessive log volume + Mitigation: Implement log rate limiting or circuit breaker patterns for repeated connection attempts + Owner: operations team + +## Implementation Notes + +- Wrap ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions +- Use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) +- Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns +- Consider adding correlation IDs or request context to error logs for distributed tracing integration + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*Failed to connect to Redis' src/ +- grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' +- dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +Accept when: +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + +## Enforcement + +- Verified by: Code review checklist requiring error logging for all external service connections +- Verified by: Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks +- Verified by: Integration tests that simulate Redis connection failures and assert expected log output +- Violation handling: Pull requests introducing cache initialization code without error logging are flagged during code review +- Violation handling: Static analysis warnings are treated as build failures in CI pipeline +- Violation handling: Production incidents involving unlogged cache failures trigger retrospective reviews and pattern reinforcement +- Exception process: Exceptions require architectural review approval with documented justification +- Exception process: Alternative observability mechanisms (e.g., metrics, tracing) must be demonstrated +- Exception process: Exception approvals are time-limited and require renewal during annual architecture reviews \ No newline at end of file diff --git a/docs/adr/4738e6e5-da0f-4f81-8170-17e1787a2708-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-rust-sdk-modules.md b/docs/adr/4738e6e5-da0f-4f81-8170-17e1787a2708-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-rust-sdk-modules.md new file mode 100644 index 000000000000..9d4bd3abba6f --- /dev/null +++ b/docs/adr/4738e6e5-da0f-4f81-8170-17e1787a2708-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-rust-sdk-modules.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Rust Sdk Modules + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. MUST: All Rust SDK modules exposing public APIs to C# MUST use csbindgen to generate C# binding code during the build process. + +## Policy Block + +- MUST All Rust SDK modules exposing public APIs to C# MUST use csbindgen to generate C# binding code during the build process. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/4882b808-5c7b-4443-b150-5b4d9e5492ec-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-multiple-fake-key.md b/docs/adr/4882b808-5c7b-4443-b150-5b4d9e5492ec-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-multiple-fake-key.md new file mode 100644 index 000000000000..0fe7e8f458b3 --- /dev/null +++ b/docs/adr/4882b808-5c7b-4443-b150-5b4d9e5492ec-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-multiple-fake-key.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Multiple Fake Key + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. MAY: Multiple fake key fixtures MAY be provided to support testing of key rotation, multi-key scenarios, or algorithm variations. + +## Policy Block + +- MAY Multiple fake key fixtures MAY be provided to support testing of key rotation, multi-key scenarios, or algorithm variations. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/49c3eb8d-cc66-4014-b066-2f29f3d823ee-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-configuration-use.md b/docs/adr/49c3eb8d-cc66-4014-b066-2f29f3d823ee-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-configuration-use.md new file mode 100644 index 000000000000..ae030ecb519e --- /dev/null +++ b/docs/adr/49c3eb8d-cc66-4014-b066-2f29f3d823ee-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-configuration-use.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Configuration Use + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. MUST: Cache configuration MUST use ConnectionMultiplexer.Connect with connection strings sourced from Bit.Core.Settings + +## Policy Block + +- MUST Cache configuration MUST use ConnectionMultiplexer.Connect with connection strings sourced from Bit.Core.Settings + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/4a4909d9-8d78-44fe-9b7e-a3dbe089be24-enforce-authorization-service-pattern-for-access-control-decisions-authorization-policies-configured.md b/docs/adr/4a4909d9-8d78-44fe-9b7e-a3dbe089be24-enforce-authorization-service-pattern-for-access-control-decisions-authorization-policies-configured.md new file mode 100644 index 000000000000..a662b172239b --- /dev/null +++ b/docs/adr/4a4909d9-8d78-44fe-9b7e-a3dbe089be24-enforce-authorization-service-pattern-for-access-control-decisions-authorization-policies-configured.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Policies Configured + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. SHOULD: Authorization policies SHOULD be configured centrally using services.AddAuthorization() in application startup configuration + +## Policy Block + +- SHOULD Authorization policies SHOULD be configured centrally using services.AddAuthorization() in application startup configuration + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/4af296a2-06e6-4fea-abfc-0a806e7df47f-adopt-http-client-abstraction-for-external-service-integration-outbound-http-communication.md b/docs/adr/4af296a2-06e6-4fea-abfc-0a806e7df47f-adopt-http-client-abstraction-for-external-service-integration-outbound-http-communication.md new file mode 100644 index 000000000000..26ff45888da4 --- /dev/null +++ b/docs/adr/4af296a2-06e6-4fea-abfc-0a806e7df47f-adopt-http-client-abstraction-for-external-service-integration-outbound-http-communication.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Outbound Http Communication + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. MUST: All outbound HTTP communication to external services MUST use framework-provided HTTP client abstractions (AddHttpClient in .NET, appropriate client libraries in Rust) + +## Policy Block + +- MUST All outbound HTTP communication to external services MUST use framework-provided HTTP client abstractions (AddHttpClient in .NET, appropriate client libraries in Rust) + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/4d319375-586c-4c89-974a-cf57f147755c-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-public-ffi-functions.md b/docs/adr/4d319375-586c-4c89-974a-cf57f147755c-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-public-ffi-functions.md new file mode 100644 index 000000000000..2a4c29cc827f --- /dev/null +++ b/docs/adr/4d319375-586c-4c89-974a-cf57f147755c-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-public-ffi-functions.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Public Ffi Functions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. MUST: Public FFI functions that return heap-allocated strings MUST transfer ownership to the C caller using c_char pointers + +## Policy Block + +- MUST Public FFI functions that return heap-allocated strings MUST transfer ownership to the C caller using c_char pointers + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/4ea57ab2-43b0-4e07-8de2-6d07829a71c8-expose-extended-cache-configuration-as-public-api-contract-redis-connection-failures.md b/docs/adr/4ea57ab2-43b0-4e07-8de2-6d07829a71c8-expose-extended-cache-configuration-as-public-api-contract-redis-connection-failures.md new file mode 100644 index 000000000000..62bd2597dd88 --- /dev/null +++ b/docs/adr/4ea57ab2-43b0-4e07-8de2-6d07829a71c8-expose-extended-cache-configuration-as-public-api-contract-redis-connection-failures.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Redis Connection Failures + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. MUST: Redis connection failures during cache initialization MUST be logged via ILogger.LogError with cache name context + +## Policy Block + +- MUST Redis connection failures during cache initialization MUST be logged via ILogger.LogError with cache name context + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/4edbda29-90a0-4c8a-97b6-e7a0bb5e58dd-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-named.md b/docs/adr/4edbda29-90a0-4c8a-97b6-e7a0bb5e58dd-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-named.md new file mode 100644 index 000000000000..2a75abf43b67 --- /dev/null +++ b/docs/adr/4edbda29-90a0-4c8a-97b6-e7a0bb5e58dd-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-named.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Named + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MUST: Authorization policies MUST be named consistently (e.g., "Scim") and referenced by name in controller authorization attributes + +## Policy Block + +- MUST Authorization policies MUST be named consistently (e.g., "Scim") and referenced by name in controller authorization attributes + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/51226e02-a611-40b7-9343-4e32cd7697ba-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-dedicated-free-string.md b/docs/adr/51226e02-a611-40b7-9343-4e32cd7697ba-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-dedicated-free-string.md new file mode 100644 index 000000000000..dd8cc732f062 --- /dev/null +++ b/docs/adr/51226e02-a611-40b7-9343-4e32cd7697ba-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-dedicated-free-string.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Dedicated Free String + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. MUST: A dedicated free_c_string function MUST be provided and documented for C callers to deallocate Rust-allocated string memory + +## Policy Block + +- MUST A dedicated free_c_string function MUST be provided and documented for C callers to deallocate Rust-allocated string memory + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/54636413-d057-4d7a-a8d4-19e29618dc76-enforce-authorization-via-policy-based-configuration-in-scim-services-domain-business-logic.md b/docs/adr/54636413-d057-4d7a-a8d4-19e29618dc76-enforce-authorization-via-policy-based-configuration-in-scim-services-domain-business-logic.md new file mode 100644 index 000000000000..2a8faed3b422 --- /dev/null +++ b/docs/adr/54636413-d057-4d7a-a8d4-19e29618dc76-enforce-authorization-via-policy-based-configuration-in-scim-services-domain-business-logic.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Domain Business Logic + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. SHOULD_NOT: Domain business logic SHOULD NOT contain inline authorization checks; enforcement SHOULD occur at policy enforcement points + +## Policy Block + +- SHOULD_NOT Domain business logic SHOULD NOT contain inline authorization checks; enforcement SHOULD occur at policy enforcement points + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/54d7258e-000f-4f7d-8079-9c820d805cdd-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-assert-jsonvaluekind.md b/docs/adr/54d7258e-000f-4f7d-8079-9c820d805cdd-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-assert-jsonvaluekind.md new file mode 100644 index 000000000000..e52f2bb52035 --- /dev/null +++ b/docs/adr/54d7258e-000f-4f7d-8079-9c820d805cdd-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-assert-jsonvaluekind.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Assert Jsonvaluekind + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. MUST: Tests MUST assert JsonValueKind.Object for complex response properties before extracting nested values + +## Policy Block + +- MUST Tests MUST assert JsonValueKind.Object for complex response properties before extracting nested values + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/551e5ab9-76a3-4125-9ac8-ad71f0e4f1f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-implementations-use-resource.md b/docs/adr/551e5ab9-76a3-4125-9ac8-ad71f0e4f1f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-implementations-use-resource.md new file mode 100644 index 000000000000..de9fc3ff52eb --- /dev/null +++ b/docs/adr/551e5ab9-76a3-4125-9ac8-ad71f0e4f1f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-implementations-use-resource.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Implementations Use Resource + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. MAY: Implementations MAY use resource pools (e.g., RSA_POOL) to manage expensive cryptographic objects across FFI calls + +## Policy Block + +- MAY Implementations MAY use resource pools (e.g., RSA_POOL) to manage expensive cryptographic objects across FFI calls + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/5544cf8d-e169-4f44-87c2-4fbb865f009f-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-restful-http-verbs.md b/docs/adr/5544cf8d-e169-4f44-87c2-4fbb865f009f-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-restful-http-verbs.md new file mode 100644 index 000000000000..7edf23451232 --- /dev/null +++ b/docs/adr/5544cf8d-e169-4f44-87c2-4fbb865f009f-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-restful-http-verbs.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Restful Http Verbs + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. SHOULD: RESTful HTTP verbs (POST, DELETE, GET, PUT, PATCH) SHOULD align with command-query semantics, with commands using POST/PUT/PATCH/DELETE and queries using GET + +## Policy Block + +- SHOULD RESTful HTTP verbs (POST, DELETE, GET, PUT, PATCH) SHOULD align with command-query semantics, with commands using POST/PUT/PATCH/DELETE and queries using GET + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/557fb6ef-5a71-4648-9beb-9a4d6f0504c2-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verify-asynchronous.md b/docs/adr/557fb6ef-5a71-4648-9beb-9a4d6f0504c2-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verify-asynchronous.md new file mode 100644 index 000000000000..eeca58727da6 --- /dev/null +++ b/docs/adr/557fb6ef-5a71-4648-9beb-9a4d6f0504c2-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verify-asynchronous.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Verify Asynchronous + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. SHOULD: Tests SHOULD verify asynchronous repository operations with Arg.Is matchers to validate complex collection arguments and DateTime parameters + +## Policy Block + +- SHOULD Tests SHOULD verify asynchronous repository operations with Arg.Is matchers to validate complex collection arguments and DateTime parameters + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/562a1fb2-8e5c-4ec8-9b46-1106e26df9fe-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-test-fixtures-cryptographic.md b/docs/adr/562a1fb2-8e5c-4ec8-9b46-1106e26df9fe-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-test-fixtures-cryptographic.md new file mode 100644 index 000000000000..06e9b3fa9b1f --- /dev/null +++ b/docs/adr/562a1fb2-8e5c-4ec8-9b46-1106e26df9fe-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-test-fixtures-cryptographic.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Test Fixtures Cryptographic + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. MUST: Test fixtures for cryptographic operations MUST use clearly labeled fake key material (e.g., _FAKE_RSA_KEY_*) to prevent accidental use in production. + +## Policy Block + +- MUST Test fixtures for cryptographic operations MUST use clearly labeled fake key material (e.g., _FAKE_RSA_KEY_*) to prevent accidental use in production. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/58ef2725-e19b-493e-9a95-7b5c168213cf-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-schemes.md b/docs/adr/58ef2725-e19b-493e-9a95-7b5c168213cf-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-schemes.md new file mode 100644 index 000000000000..bb8b331f4e54 --- /dev/null +++ b/docs/adr/58ef2725-e19b-493e-9a95-7b5c168213cf-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-schemes.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Test Authentication Schemes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. SHOULD: Test authentication schemes SHOULD include organizational context claims (e.g., 'orgadmin' with organization ID) to simulate multi-tenant scenarios + +## Policy Block + +- SHOULD Test authentication schemes SHOULD include organizational context claims (e.g., 'orgadmin' with organization ID) to simulate multi-tenant scenarios + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/5a99a8f6-738b-4a0c-8d4b-af692c7977fb-enforce-authorization-service-pattern-for-access-control-decisions-authorization-failures-throw.md b/docs/adr/5a99a8f6-738b-4a0c-8d4b-af692c7977fb-enforce-authorization-service-pattern-for-access-control-decisions-authorization-failures-throw.md new file mode 100644 index 000000000000..ae6f8dc18472 --- /dev/null +++ b/docs/adr/5a99a8f6-738b-4a0c-8d4b-af692c7977fb-enforce-authorization-service-pattern-for-access-control-decisions-authorization-failures-throw.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Failures Throw + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MUST: Authorization failures MUST throw NotFoundException or return appropriate HTTP error responses (400 Bad Request, 401 Unauthorized, 403 Forbidden) based on the authorization context + +## Policy Block + +- MUST Authorization failures MUST throw NotFoundException or return appropriate HTTP error responses (400 Bad Request, 401 Unauthorized, 403 Forbidden) based on the authorization context + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/5cd6ec70-a27a-44ff-a08f-ccf37d7b0e93-log-redis-connection-failures-in-distributed-cache-extensions-error-log-entries.md b/docs/adr/5cd6ec70-a27a-44ff-a08f-ccf37d7b0e93-log-redis-connection-failures-in-distributed-cache-extensions-error-log-entries.md new file mode 100644 index 000000000000..79a4ee192b98 --- /dev/null +++ b/docs/adr/5cd6ec70-a27a-44ff-a08f-ccf37d7b0e93-log-redis-connection-failures-in-distributed-cache-extensions-error-log-entries.md @@ -0,0 +1,100 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Error Log Entries + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses StackExchangeRedis as a distributed cache implementation via Microsoft.Extensions.Caching.StackExchangeRedis +- Redis connection establishment occurs in ExtendedCacheServiceCollectionExtensions during service registration, requiring error visibility for operational diagnostics +- The pattern appears in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs where ConnectionMultiplexer.Connect operations are wrapped with structured logging +- Cache initialization failures must be observable to distinguish between configuration errors, network issues, and Redis availability problems + +## Problem Statement + +When Redis connection failures occur during distributed cache initialization, operators and developers need structured, contextual error information to diagnose whether the failure stems from misconfiguration, network connectivity, or Redis service availability, without relying on unhandled exceptions or silent failures. + +## Decision + +1. MUST: Error log entries for Redis connection failures MUST include the cache name as a structured logging parameter (e.g., {CacheName}) + +## Policy Block + +- MUST Error log entries for Redis connection failures MUST include the cache name as a structured logging parameter (e.g., {CacheName}) + +## Rationale + +- The evidence shows explicit error logging with logger?.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) in ExtendedCacheServiceCollectionExtensions.cs, establishing a pattern of structured error reporting +- Redis connection failures are critical operational events that require immediate visibility, as they directly impact application caching capabilities and performance +- Structured logging with cache name context enables filtering and alerting on specific cache instances in multi-cache deployments +- The pattern uses Microsoft.Extensions.Logging abstractions, ensuring compatibility with various logging providers and observability platforms + +## Consequences + +Positive: +- Operators gain immediate visibility into Redis connection failures through structured logs with contextual information +- Diagnostic time is reduced by including cache name and exception details in a single log entry +- Structured logging parameters enable automated alerting and filtering in log aggregation systems +- The pattern integrates with existing Microsoft.Extensions.Logging infrastructure without additional dependencies + +Negative: +- Log volume increases during Redis outages or misconfigurations, potentially impacting log storage costs +- Sensitive connection string information must be carefully sanitized to avoid credential leakage in logs +- The null-conditional operator (logger?) allows silent failures if logging is not configured, reducing error visibility + +## Alternatives + +- Allow ConnectionMultiplexer.Connect exceptions to propagate unhandled, relying on global exception handlers (rejected) + Rejected because: Unhandled exceptions during service registration cause application startup failures without contextual information about which cache failed or why + When valid: In scenarios where fail-fast behavior is required and any cache initialization failure should prevent application startup +- Use health checks to detect Redis connectivity issues post-startup rather than logging during initialization (rejected) + Rejected because: Health checks provide runtime monitoring but do not capture initialization-time failures or provide immediate diagnostic context during startup + When valid: As a complementary approach for ongoing runtime monitoring after successful initialization +- Implement retry logic with exponential backoff before logging connection failures (deferred) + Rejected because: Retry logic adds complexity and startup latency; the current pattern focuses on observability rather than resilience + When valid: When transient network issues are common and automatic recovery is preferred over immediate failure reporting + +## Risks + +- Connection string credentials may be inadvertently logged if error messages include full connection details + Mitigation: Sanitize connection strings before logging and rely on structured parameters that exclude sensitive data + Owner: engineering team +- The null-conditional operator (logger?) allows silent failures when ILogger is not injected or configured + Mitigation: Ensure logging infrastructure is configured before cache service registration or use non-null logger instances + Owner: engineering team +- High-frequency connection failures during Redis outages may generate excessive log volume + Mitigation: Implement log rate limiting or circuit breaker patterns for repeated connection attempts + Owner: operations team + +## Implementation Notes + +- Wrap ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions +- Use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) +- Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns +- Consider adding correlation IDs or request context to error logs for distributed tracing integration + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*Failed to connect to Redis' src/ +- grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' +- dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +Accept when: +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + +## Enforcement + +- Verified by: Code review checklist requiring error logging for all external service connections +- Verified by: Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks +- Verified by: Integration tests that simulate Redis connection failures and assert expected log output +- Violation handling: Pull requests introducing cache initialization code without error logging are flagged during code review +- Violation handling: Static analysis warnings are treated as build failures in CI pipeline +- Violation handling: Production incidents involving unlogged cache failures trigger retrospective reviews and pattern reinforcement +- Exception process: Exceptions require architectural review approval with documented justification +- Exception process: Alternative observability mechanisms (e.g., metrics, tracing) must be demonstrated +- Exception process: Exception approvals are time-limited and require renewal during annual architecture reviews \ No newline at end of file diff --git a/docs/adr/5d4a8535-38ea-4839-8a6d-38029726ae65-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-not.md b/docs/adr/5d4a8535-38ea-4839-8a6d-38029726ae65-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-not.md new file mode 100644 index 000000000000..3748c91df2e3 --- /dev/null +++ b/docs/adr/5d4a8535-38ea-4839-8a6d-38029726ae65-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-not.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Not + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. MUST_NOT: FFI functions MUST NOT assume input c_char pointers are valid UTF-8 without explicit validation + +## Policy Block + +- MUST_NOT FFI functions MUST NOT assume input c_char pointers are valid UTF-8 without explicit validation + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/5dbb6704-3c65-4f9a-b03b-68cf4c7f95b9-establish-http-client-boundaries-for-external-service-integration-named-http-clients.md b/docs/adr/5dbb6704-3c65-4f9a-b03b-68cf4c7f95b9-establish-http-client-boundaries-for-external-service-integration-named-http-clients.md new file mode 100644 index 000000000000..4b8c45d92522 --- /dev/null +++ b/docs/adr/5dbb6704-3c65-4f9a-b03b-68cf4c7f95b9-establish-http-client-boundaries-for-external-service-integration-named-http-clients.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: Named Http Clients + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. MUST: Named HTTP clients MUST be used when specific configuration or handler pipelines are required for distinct external service integrations + +## Policy Block + +- MUST Named HTTP clients MUST be used when specific configuration or handler pipelines are required for distinct external service integrations + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/5e080c9b-be10-4cf4-aa70-fe5e5d4cf4a3-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-exception-logging-within.md b/docs/adr/5e080c9b-be10-4cf4-aa70-fe5e5d4cf4a3-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-exception-logging-within.md new file mode 100644 index 000000000000..72744828465a --- /dev/null +++ b/docs/adr/5e080c9b-be10-4cf4-aa70-fe5e5d4cf4a3-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-exception-logging-within.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Exception Logging Within + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. MUST: Exception logging within authorized actions MUST use LogError with the exception object as the first parameter to preserve stack traces and exception metadata + +## Policy Block + +- MUST Exception logging within authorized actions MUST use LogError with the exception object as the first parameter to preserve stack traces and exception metadata + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/60f4f273-53c2-4a31-b733-f88485f7d07b-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-bit-adminconsole.md b/docs/adr/60f4f273-53c2-4a31-b733-f88485f7d07b-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-bit-adminconsole.md new file mode 100644 index 000000000000..abd6fed52310 --- /dev/null +++ b/docs/adr/60f4f273-53c2-4a31-b733-f88485f7d07b-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-bit-adminconsole.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Bit Adminconsole + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MUST: Controllers in the Bit.Api.AdminConsole namespace managing organization user operations MUST inject IAuthorizationService as a constructor dependency + +## Policy Block + +- MUST Controllers in the Bit.Api.AdminConsole namespace managing organization user operations MUST inject IAuthorizationService as a constructor dependency + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/613d377b-9885-4202-8c35-5dc7040c6b9b-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-property-names.md b/docs/adr/613d377b-9885-4202-8c35-5dc7040c6b9b-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-property-names.md new file mode 100644 index 000000000000..5983cc266f0f --- /dev/null +++ b/docs/adr/613d377b-9885-4202-8c35-5dc7040c6b9b-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-property-names.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Dbset Property Names + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. MUST: DbSet property names MUST use plural noun forms that clearly identify the entity collection (e.g., DbSet Users, DbSet Ciphers) + +## Policy Block + +- MUST DbSet property names MUST use plural noun forms that clearly identify the entity collection (e.g., DbSet Users, DbSet Ciphers) + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/61b87c11-8189-45b9-bdb0-07a0b193e382-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-number.md b/docs/adr/61b87c11-8189-45b9-bdb0-07a0b193e382-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-number.md new file mode 100644 index 000000000000..626915656f29 --- /dev/null +++ b/docs/adr/61b87c11-8189-45b9-bdb0-07a0b193e382-verify-logger-invocations-in-unit-tests-for-observability-components-tests-verify-number.md @@ -0,0 +1,116 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Tests Verify Number + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Unit tests in the codebase verify that logger dependencies are invoked with expected warning messages during error conditions +- The pattern appears in test files for SCIM group operations (PatchGroupCommandTests.cs) and authentication request services (AuthRequestServiceTests.cs) +- Tests use dependency injection providers to retrieve ILogger instances and assert that specific log methods (LogWarning) are called with exact message strings +- This testing approach treats logging as a verifiable behavior rather than an implementation detail, ensuring observability contracts are maintained + +## Problem Statement + +Without explicit verification of logging behavior in unit tests, critical diagnostic messages may be removed or modified during refactoring, degrading operational observability and making production issues harder to diagnose. The codebase needs a consistent approach to ensure logging contracts are tested alongside business logic. + +## Decision + +1. MAY: Tests MAY verify the number of times a logger method was called using Received(n) syntax when call frequency is significant + +## Policy Block + +- MAY Tests MAY verify the number of times a logger method was called using Received(n) syntax when call frequency is significant + +In scope: +- Unit tests for services and commands that include ILogger dependencies +- Test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected +- Components in the Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging + +Out of scope: +- Integration tests where actual logging infrastructure is used rather than mocked +- Performance tests where logger verification overhead is unacceptable +- Tests for components that do not have logging dependencies +- Logging infrastructure implementation tests (e.g., testing the logger itself) + +Exceptions: +- EX-001: The logging behavior is purely diagnostic and not part of any operational contract or alerting logic + +## Rationale + +- The evidence shows 2 test files explicitly verifying ILogger invocations with specific messages, indicating an established pattern for treating logging as testable behavior +- Verifying logger calls ensures that operational observability contracts are maintained across refactoring and code changes +- The pattern uses dependency injection and mocking frameworks (AutoFixture, NSubstitute) already present in the codebase, requiring no additional infrastructure +- Testing logging behavior provides early detection of changes that could impact production diagnostics and incident response + +## Consequences + +Positive: +- Logging contracts become explicit and protected by automated tests, preventing silent degradation of observability +- Developers receive immediate feedback when refactoring removes or changes critical diagnostic messages +- The pattern integrates naturally with existing dependency injection and unit testing infrastructure +- Production incident response is improved through guaranteed availability of expected log messages + +Negative: +- Unit tests become coupled to logging implementation details, potentially increasing test maintenance burden +- Test verbosity increases as logger verification adds additional assertions to each test case +- Refactoring log messages requires updating corresponding test assertions, slowing down minor message improvements +- Over-specification of logging behavior may discourage developers from adding helpful diagnostic logging + +## Alternatives + +- Treat logging as an implementation detail and do not verify logger invocations in unit tests (rejected) + Rejected because: This approach allows critical diagnostic messages to be removed during refactoring without detection, degrading production observability. The evidence shows the codebase has already adopted explicit logger verification. + When valid: For purely diagnostic logging that has no operational significance and is not used for alerting or incident response +- Use integration tests with actual logging infrastructure to verify log output (deferred) + Rejected because: Integration tests provide slower feedback and higher maintenance cost. This approach complements rather than replaces unit-level verification. + When valid: For end-to-end validation of logging configuration, formatting, and sink behavior in staging environments +- Implement custom logging abstractions that separate testable events from log formatting (rejected) + Rejected because: This requires significant infrastructure changes and abstracts away the ILogger pattern already established in the codebase. The current approach works with existing dependencies. + When valid: For greenfield projects or major logging infrastructure redesigns where decoupling events from formatting provides clear architectural benefits + +## Risks + +- Over-specification of log messages in tests creates brittleness, where minor message improvements require widespread test updates + Mitigation: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules + Owner: Engineering team +- Developers may avoid adding helpful logging to avoid increasing test complexity and maintenance burden + Mitigation: Establish clear guidelines on which logging calls require verification (error conditions, security events, operational alerts) versus which are purely diagnostic + Owner: Engineering team and tech leads +- Logger verification may not catch issues with log message formatting, structured logging parameters, or sink configuration + Mitigation: Complement unit-level logger verification with integration tests that validate actual log output in representative environments + Owner: QA and engineering team + +## Implementation Notes + +- Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure +- Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.) +- Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract +- Document in test comments when logger verification is intentionally omitted for purely diagnostic logging +- Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns + +## Continuation Context + + +Verify commands: +- grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts + +## Enforcement + +- Verified by: Code review checks for logger verification in unit tests covering error conditions and operational events +- Verified by: CI pipeline runs unit tests that include logger verification assertions +- Verified by: Static analysis or custom linting rules to detect ILogger dependencies without corresponding test verification +- Violation handling: Code review feedback requests addition of logger verification for components with ILogger dependencies +- Violation handling: Pull requests may be blocked if critical error paths lack logging verification +- Violation handling: Retrospective analysis of production incidents identifies missing logging that should have been tested +- Exception process: Developer documents in test comments why logger verification is omitted (e.g., purely diagnostic logging) +- Exception process: Team lead approves exception during code review based on operational significance assessment +- Exception process: Exception is recorded in test file comments for future reference \ No newline at end of file diff --git a/docs/adr/625af6eb-2999-45fa-865d-97ab13837d42-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-authentication-failure-tests.md b/docs/adr/625af6eb-2999-45fa-865d-97ab13837d42-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-authentication-failure-tests.md new file mode 100644 index 000000000000..8412ba8ed929 --- /dev/null +++ b/docs/adr/625af6eb-2999-45fa-865d-97ab13837d42-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-authentication-failure-tests.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Authentication Failure Tests + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. MUST: Authentication failure tests MUST validate specific error message content using Assert.Equal with expected error strings + +## Policy Block + +- MUST Authentication failure tests MUST validate specific error message content using Assert.Equal with expected error strings + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/652092c8-86ba-4e27-a202-23567b7338de-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-memory-allocated-ffi.md b/docs/adr/652092c8-86ba-4e27-a202-23567b7338de-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-memory-allocated-ffi.md new file mode 100644 index 000000000000..dc85f6e9ac3a --- /dev/null +++ b/docs/adr/652092c8-86ba-4e27-a202-23567b7338de-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-memory-allocated-ffi.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Memory Allocated Ffi + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. SHOULD: Memory allocated for FFI string returns SHOULD be freed using a dedicated free_c_string function to prevent leaks + +## Policy Block + +- SHOULD Memory allocated for FFI string returns SHOULD be freed using a dedicated free_c_string function to prevent leaks + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/69102dad-97f7-491e-88fe-9133675beb97-register-core-infrastructure-services-via-dependency-injection-container-authorization-policies-use.md b/docs/adr/69102dad-97f7-491e-88fe-9133675beb97-register-core-infrastructure-services-via-dependency-injection-container-authorization-policies-use.md new file mode 100644 index 000000000000..2dfb343a5c84 --- /dev/null +++ b/docs/adr/69102dad-97f7-491e-88fe-9133675beb97-register-core-infrastructure-services-via-dependency-injection-container-authorization-policies-use.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Authorization Policies Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. SHOULD: Authorization policies SHOULD use RequireAssertion for complex claim-based authorization logic that cannot be expressed through simple role or claim requirements + +## Policy Block + +- SHOULD Authorization policies SHOULD use RequireAssertion for complex claim-based authorization logic that cannot be expressed through simple role or claim requirements + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/6a74e276-66db-449a-929c-65a5f57ce685-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md b/docs/adr/6a74e276-66db-449a-929c-65a5f57ce685-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md new file mode 100644 index 000000000000..a4398ea5a705 --- /dev/null +++ b/docs/adr/6a74e276-66db-449a-929c-65a5f57ce685-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi String Validation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. SHOULD: FFI string validation SHOULD occur at the earliest point in the function before any cryptographic operations are performed + +## Policy Block + +- SHOULD FFI string validation SHOULD occur at the earliest point in the function before any cryptographic operations are performed + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/6a8737dc-387f-416a-afe6-4d35b3083143-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-checks-occur.md b/docs/adr/6a8737dc-387f-416a-afe6-4d35b3083143-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-checks-occur.md new file mode 100644 index 000000000000..61330f995749 --- /dev/null +++ b/docs/adr/6a8737dc-387f-416a-afe6-4d35b3083143-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-checks-occur.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Authorization Checks Occur + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. SHOULD: Authorization checks SHOULD occur before expensive operations such as database writes or external service calls + +## Policy Block + +- SHOULD Authorization checks SHOULD occur before expensive operations such as database writes or external service calls + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/6d08223f-13b7-41cc-87df-78b85c3f2721-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-http-endpoint-methods.md b/docs/adr/6d08223f-13b7-41cc-87df-78b85c3f2721-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-http-endpoint-methods.md new file mode 100644 index 000000000000..600fda3675ce --- /dev/null +++ b/docs/adr/6d08223f-13b7-41cc-87df-78b85c3f2721-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-http-endpoint-methods.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Http Endpoint Methods + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. MUST: HTTP endpoint methods MUST map to command or query interface methods rather than performing direct data access or persistence operations + +## Policy Block + +- MUST HTTP endpoint methods MUST map to command or query interface methods rather than performing direct data access or persistence operations + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/6e7b7016-eb84-47d3-8a29-a78cd5f8e5b4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connections-established.md b/docs/adr/6e7b7016-eb84-47d3-8a29-a78cd5f8e5b4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connections-established.md new file mode 100644 index 000000000000..cda9fdd3bd00 --- /dev/null +++ b/docs/adr/6e7b7016-eb84-47d3-8a29-a78cd5f8e5b4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connections-established.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Redis Connections Established + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. MUST: Redis connections MUST be established through StackExchangeRedis ConnectionMultiplexer.Connect with connection string configuration + +## Policy Block + +- MUST Redis connections MUST be established through StackExchangeRedis ConnectionMultiplexer.Connect with connection string configuration + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/6ee5e5c9-4eba-4aa1-a0c7-c45396eddc9f-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connection-failures.md b/docs/adr/6ee5e5c9-4eba-4aa1-a0c7-c45396eddc9f-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connection-failures.md new file mode 100644 index 000000000000..f13d44d9a721 --- /dev/null +++ b/docs/adr/6ee5e5c9-4eba-4aa1-a0c7-c45396eddc9f-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-redis-connection-failures.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Redis Connection Failures + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. MUST: Redis connection failures MUST be logged with structured logging including cache name context using ILogger.LogError + +## Policy Block + +- MUST Redis connection failures MUST be logged with structured logging including cache name context using ILogger.LogError + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/716f591a-8197-4b3a-9b4e-8289d3220344-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-servers-inject.md b/docs/adr/716f591a-8197-4b3a-9b4e-8289d3220344-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-servers-inject.md new file mode 100644 index 000000000000..450076a3c1ac --- /dev/null +++ b/docs/adr/716f591a-8197-4b3a-9b4e-8289d3220344-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-servers-inject.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Servers Inject + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. SHOULD: Test servers SHOULD inject NoopMailService or equivalent test doubles for external service dependencies + +## Policy Block + +- SHOULD Test servers SHOULD inject NoopMailService or equivalent test doubles for external service dependencies + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/71f1e1e1-3305-40ed-8ef5-c8334377ee96-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-modules-use.md b/docs/adr/71f1e1e1-3305-40ed-8ef5-c8334377ee96-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-modules-use.md new file mode 100644 index 000000000000..c947a239ff5d --- /dev/null +++ b/docs/adr/71f1e1e1-3305-40ed-8ef5-c8334377ee96-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-modules-use.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Modules Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. MAY: FFI modules MAY use additional validation layers (length checks, character set validation) beyond CStr/CString for defense in depth + +## Policy Block + +- MAY FFI modules MAY use additional validation layers (length checks, character set validation) beyond CStr/CString for defense in depth + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/72668b21-de9e-48dc-a3e4-390f41bff7b5-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-boundaries-coordinate-multiple.md b/docs/adr/72668b21-de9e-48dc-a3e4-390f41bff7b5-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-boundaries-coordinate-multiple.md new file mode 100644 index 000000000000..7655e338725f --- /dev/null +++ b/docs/adr/72668b21-de9e-48dc-a3e4-390f41bff7b5-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-boundaries-coordinate-multiple.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Boundaries Coordinate Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. MAY: API boundaries MAY coordinate multiple command or query operations within a single endpoint method when representing a cohesive business operation + +## Policy Block + +- MAY API boundaries MAY coordinate multiple command or query operations within a single endpoint method when representing a cohesive business operation + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/730eeb26-7617-47a6-ac66-d0b722c94a7c-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-handle-aggregate.md b/docs/adr/730eeb26-7617-47a6-ac66-d0b722c94a7c-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-handle-aggregate.md new file mode 100644 index 000000000000..26265aae37c4 --- /dev/null +++ b/docs/adr/730eeb26-7617-47a6-ac66-d0b722c94a7c-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-handle-aggregate.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Controllers Handle Aggregate + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. MUST: API controllers MUST handle aggregate exceptions for batch operations and domain-specific exceptions (e.g., SceneExecutionException) for single operations, returning structured error responses + +## Policy Block + +- MUST API controllers MUST handle aggregate exceptions for batch operations and domain-specific exceptions (e.g., SceneExecutionException) for single operations, returning structured error responses + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/74822a96-3248-4fde-b4ba-fae354caf724-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-custom-authorization-requirements.md b/docs/adr/74822a96-3248-4fde-b4ba-fae354caf724-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-custom-authorization-requirements.md new file mode 100644 index 000000000000..efd12750a7c2 --- /dev/null +++ b/docs/adr/74822a96-3248-4fde-b4ba-fae354caf724-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-custom-authorization-requirements.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Custom Authorization Requirements + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. SHOULD: Custom authorization requirements SHOULD be defined as strongly-typed requirement classes that implement IAuthorizationRequirement and are used with the generic Authorize attribute + +## Policy Block + +- SHOULD Custom authorization requirements SHOULD be defined as strongly-typed requirement classes that implement IAuthorizationRequirement and are used with the generic Authorize attribute + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/74bf715a-53ae-4c13-be5f-a29c89c0478b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-http-response-types.md b/docs/adr/74bf715a-53ae-4c13-be5f-a29c89c0478b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-http-response-types.md new file mode 100644 index 000000000000..a5a8637ef052 --- /dev/null +++ b/docs/adr/74bf715a-53ae-4c13-be5f-a29c89c0478b-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-http-response-types.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Http Response Types + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. MUST: HTTP response types MUST implement IResult interface to ensure compatibility with ASP.NET Core endpoint execution pipeline + +## Policy Block + +- MUST HTTP response types MUST implement IResult interface to ensure compatibility with ASP.NET Core endpoint execution pipeline + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/7507ed7f-d610-4f43-853a-2f85cc6254d9-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-messages-describe.md b/docs/adr/7507ed7f-d610-4f43-853a-2f85cc6254d9-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-messages-describe.md new file mode 100644 index 000000000000..7e66aad15c82 --- /dev/null +++ b/docs/adr/7507ed7f-d610-4f43-853a-2f85cc6254d9-use-structured-logging-with-contextual-parameters-for-external-service-failures-log-messages-describe.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Log Messages Describe + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. SHOULD: Log messages should describe the failure context and the state of the primary operation (e.g., 'Database was updated successfully' when Stripe sync fails) + +## Policy Block + +- SHOULD Log messages should describe the failure context and the state of the primary operation (e.g., 'Database was updated successfully' when Stripe sync fails) + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/753e6ac5-2d04-49b3-9c29-48bf5ef452fb-adopt-attribute-based-authorization-model-for-controller-actions-controller-actions-that.md b/docs/adr/753e6ac5-2d04-49b3-9c29-48bf5ef452fb-adopt-attribute-based-authorization-model-for-controller-actions-controller-actions-that.md new file mode 100644 index 000000000000..660cd118a020 --- /dev/null +++ b/docs/adr/753e6ac5-2d04-49b3-9c29-48bf5ef452fb-adopt-attribute-based-authorization-model-for-controller-actions-controller-actions-that.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Controller Actions That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. MUST: All controller actions that require authorization MUST declare authorization requirements using [Authorize] or [Authorize] attributes + +## Policy Block + +- MUST All controller actions that require authorization MUST declare authorization requirements using [Authorize] or [Authorize] attributes + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/758dcc20-8b27-421a-a3a3-d27e3e2f5d57-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-connect.md b/docs/adr/758dcc20-8b27-421a-a3a3-d27e3e2f5d57-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-connect.md new file mode 100644 index 000000000000..9d74a77ed42b --- /dev/null +++ b/docs/adr/758dcc20-8b27-421a-a3a3-d27e3e2f5d57-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-connect.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Integration Tests Connect + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. MUST: Integration tests for /connect/token endpoints MUST use System.Text.Json for parsing and validating JSON response structures + +## Policy Block + +- MUST Integration tests for /connect/token endpoints MUST use System.Text.Json for parsing and validating JSON response structures + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/76807d1e-075a-4dfb-8034-4d3ce093ebe1-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md b/docs/adr/76807d1e-075a-4dfb-8034-4d3ce093ebe1-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md new file mode 100644 index 000000000000..421b975532b5 --- /dev/null +++ b/docs/adr/76807d1e-075a-4dfb-8034-4d3ce093ebe1-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md @@ -0,0 +1,116 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Logger Verification Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Unit tests in the codebase verify that logger dependencies are invoked with expected warning messages during error conditions +- The pattern appears in test files for SCIM group operations (PatchGroupCommandTests.cs) and authentication request services (AuthRequestServiceTests.cs) +- Tests use dependency injection providers to retrieve ILogger instances and assert that specific log methods (LogWarning) are called with exact message strings +- This testing approach treats logging as a verifiable behavior rather than an implementation detail, ensuring observability contracts are maintained + +## Problem Statement + +Without explicit verification of logging behavior in unit tests, critical diagnostic messages may be removed or modified during refactoring, degrading operational observability and making production issues harder to diagnose. The codebase needs a consistent approach to ensure logging contracts are tested alongside business logic. + +## Decision + +1. MUST: Logger verification MUST use the dependency injection provider pattern (e.g., sutProvider.GetDependency>()) to retrieve logger instances + +## Policy Block + +- MUST Logger verification MUST use the dependency injection provider pattern (e.g., sutProvider.GetDependency>()) to retrieve logger instances + +In scope: +- Unit tests for services and commands that include ILogger dependencies +- Test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected +- Components in the Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging + +Out of scope: +- Integration tests where actual logging infrastructure is used rather than mocked +- Performance tests where logger verification overhead is unacceptable +- Tests for components that do not have logging dependencies +- Logging infrastructure implementation tests (e.g., testing the logger itself) + +Exceptions: +- EX-001: The logging behavior is purely diagnostic and not part of any operational contract or alerting logic + +## Rationale + +- The evidence shows 2 test files explicitly verifying ILogger invocations with specific messages, indicating an established pattern for treating logging as testable behavior +- Verifying logger calls ensures that operational observability contracts are maintained across refactoring and code changes +- The pattern uses dependency injection and mocking frameworks (AutoFixture, NSubstitute) already present in the codebase, requiring no additional infrastructure +- Testing logging behavior provides early detection of changes that could impact production diagnostics and incident response + +## Consequences + +Positive: +- Logging contracts become explicit and protected by automated tests, preventing silent degradation of observability +- Developers receive immediate feedback when refactoring removes or changes critical diagnostic messages +- The pattern integrates naturally with existing dependency injection and unit testing infrastructure +- Production incident response is improved through guaranteed availability of expected log messages + +Negative: +- Unit tests become coupled to logging implementation details, potentially increasing test maintenance burden +- Test verbosity increases as logger verification adds additional assertions to each test case +- Refactoring log messages requires updating corresponding test assertions, slowing down minor message improvements +- Over-specification of logging behavior may discourage developers from adding helpful diagnostic logging + +## Alternatives + +- Treat logging as an implementation detail and do not verify logger invocations in unit tests (rejected) + Rejected because: This approach allows critical diagnostic messages to be removed during refactoring without detection, degrading production observability. The evidence shows the codebase has already adopted explicit logger verification. + When valid: For purely diagnostic logging that has no operational significance and is not used for alerting or incident response +- Use integration tests with actual logging infrastructure to verify log output (deferred) + Rejected because: Integration tests provide slower feedback and higher maintenance cost. This approach complements rather than replaces unit-level verification. + When valid: For end-to-end validation of logging configuration, formatting, and sink behavior in staging environments +- Implement custom logging abstractions that separate testable events from log formatting (rejected) + Rejected because: This requires significant infrastructure changes and abstracts away the ILogger pattern already established in the codebase. The current approach works with existing dependencies. + When valid: For greenfield projects or major logging infrastructure redesigns where decoupling events from formatting provides clear architectural benefits + +## Risks + +- Over-specification of log messages in tests creates brittleness, where minor message improvements require widespread test updates + Mitigation: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules + Owner: Engineering team +- Developers may avoid adding helpful logging to avoid increasing test complexity and maintenance burden + Mitigation: Establish clear guidelines on which logging calls require verification (error conditions, security events, operational alerts) versus which are purely diagnostic + Owner: Engineering team and tech leads +- Logger verification may not catch issues with log message formatting, structured logging parameters, or sink configuration + Mitigation: Complement unit-level logger verification with integration tests that validate actual log output in representative environments + Owner: QA and engineering team + +## Implementation Notes + +- Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure +- Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.) +- Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract +- Document in test comments when logger verification is intentionally omitted for purely diagnostic logging +- Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns + +## Continuation Context + + +Verify commands: +- grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts + +## Enforcement + +- Verified by: Code review checks for logger verification in unit tests covering error conditions and operational events +- Verified by: CI pipeline runs unit tests that include logger verification assertions +- Verified by: Static analysis or custom linting rules to detect ILogger dependencies without corresponding test verification +- Violation handling: Code review feedback requests addition of logger verification for components with ILogger dependencies +- Violation handling: Pull requests may be blocked if critical error paths lack logging verification +- Violation handling: Retrospective analysis of production incidents identifies missing logging that should have been tested +- Exception process: Developer documents in test comments why logger verification is omitted (e.g., purely diagnostic logging) +- Exception process: Team lead approves exception during code review based on operational significance assessment +- Exception process: Exception is recorded in test file comments for future reference \ No newline at end of file diff --git a/docs/adr/76873ea9-7582-4103-8bba-d3a38075aac8-use-system-text-json-for-scim-api-data-access-serialization-test-factories-use.md b/docs/adr/76873ea9-7582-4103-8bba-d3a38075aac8-use-system-text-json-for-scim-api-data-access-serialization-test-factories-use.md new file mode 100644 index 000000000000..8ecd63d85014 --- /dev/null +++ b/docs/adr/76873ea9-7582-4103-8bba-d3a38075aac8-use-system-text-json-for-scim-api-data-access-serialization-test-factories-use.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Test Factories Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. MAY: Test factories MAY use custom AuthenticationHandler implementations for simulating SCIM client authentication + +## Policy Block + +- MAY Test factories MAY use custom AuthenticationHandler implementations for simulating SCIM client authentication + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/76ba54b2-0ca8-4aca-b2e1-b8c4cce7f095-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-handlers-inherit.md b/docs/adr/76ba54b2-0ca8-4aca-b2e1-b8c4cce7f095-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-handlers-inherit.md new file mode 100644 index 000000000000..8ff65ce71d50 --- /dev/null +++ b/docs/adr/76ba54b2-0ca8-4aca-b2e1-b8c4cce7f095-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-handlers-inherit.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authentication Handlers Inherit + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. MUST: Authentication handlers MUST inherit from AuthenticationHandler and implement HandleAuthenticateAsync to return AuthenticateResult with ClaimsPrincipal + +## Policy Block + +- MUST Authentication handlers MUST inherit from AuthenticationHandler and implement HandleAuthenticateAsync to return AuthenticateResult with ClaimsPrincipal + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/77bc5fcb-f89e-4ff6-abb4-4d1494ae4c74-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-protected-controller-endpoints.md b/docs/adr/77bc5fcb-f89e-4ff6-abb4-4d1494ae4c74-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-protected-controller-endpoints.md new file mode 100644 index 000000000000..5a7f699ee03e --- /dev/null +++ b/docs/adr/77bc5fcb-f89e-4ff6-abb4-4d1494ae4c74-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-protected-controller-endpoints.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Protected Controller Endpoints + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. MUST: All protected controller endpoints MUST use IAuthorizationService to evaluate authorization requirements before granting access to resources + +## Policy Block + +- MUST All protected controller endpoints MUST use IAuthorizationService to evaluate authorization requirements before granting access to resources + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/781f6b28-4c7f-4deb-817d-762221188c8c-enforce-authorization-service-pattern-for-access-control-decisions-authorization-checks-performed.md b/docs/adr/781f6b28-4c7f-4deb-817d-762221188c8c-enforce-authorization-service-pattern-for-access-control-decisions-authorization-checks-performed.md new file mode 100644 index 000000000000..41e25235d15c --- /dev/null +++ b/docs/adr/781f6b28-4c7f-4deb-817d-762221188c8c-enforce-authorization-service-pattern-for-access-control-decisions-authorization-checks-performed.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Authorization Checks Performed + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MUST: Authorization checks MUST be performed using policy-based authorization with named requirements (e.g., ManageUsersRequirement, ManageAccountRecoveryRequirement) rather than inline authorization logic + +## Policy Block + +- MUST Authorization checks MUST be performed using policy-based authorization with named requirements (e.g., ManageUsersRequirement, ManageAccountRecoveryRequirement) rather than inline authorization logic + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/78593eda-af88-4bd6-9784-a3e7ccb7e150-establish-http-client-boundaries-for-external-service-integration-http-clients-that.md b/docs/adr/78593eda-af88-4bd6-9784-a3e7ccb7e150-establish-http-client-boundaries-for-external-service-integration-http-clients-that.md new file mode 100644 index 000000000000..d39dee36f23f --- /dev/null +++ b/docs/adr/78593eda-af88-4bd6-9784-a3e7ccb7e150-establish-http-client-boundaries-for-external-service-integration-http-clients-that.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: Http Clients That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. MUST: HTTP clients that interact with user-supplied URLs MUST include SSRF protection through AddSsrfProtection() handler registration + +## Policy Block + +- MUST HTTP clients that interact with user-supplied URLs MUST include SSRF protection through AddSsrfProtection() handler registration + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/789a3481-a7e9-43af-aac1-53564623b268-adopt-attribute-based-authorization-model-for-controller-actions-custom-authorization-requirements.md b/docs/adr/789a3481-a7e9-43af-aac1-53564623b268-adopt-attribute-based-authorization-model-for-controller-actions-custom-authorization-requirements.md new file mode 100644 index 000000000000..9a1e23572f50 --- /dev/null +++ b/docs/adr/789a3481-a7e9-43af-aac1-53564623b268-adopt-attribute-based-authorization-model-for-controller-actions-custom-authorization-requirements.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Custom Authorization Requirements + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. MUST: Custom authorization requirements MUST be expressed as strongly-typed requirement classes (e.g., ManageUsersRequirement, ProviderAdminRequirement) applied via generic [Authorize] attributes + +## Policy Block + +- MUST Custom authorization requirements MUST be expressed as strongly-typed requirement classes (e.g., ManageUsersRequirement, ProviderAdminRequirement) applied via generic [Authorize] attributes + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/79299188-39e7-484d-b952-b1e8cb4262cc-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-use-icurrentcontext.md b/docs/adr/79299188-39e7-484d-b952-b1e8cb4262cc-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-use-icurrentcontext.md new file mode 100644 index 000000000000..528b2222f54f --- /dev/null +++ b/docs/adr/79299188-39e7-484d-b952-b1e8cb4262cc-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-controllers-use-icurrentcontext.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Controllers Use Icurrentcontext + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. SHOULD: Controllers SHOULD use ICurrentContext for additional runtime authorization checks when attribute-based authorization alone is insufficient + +## Policy Block + +- SHOULD Controllers SHOULD use ICurrentContext for additional runtime authorization checks when attribute-based authorization alone is insufficient + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/79b476ff-5365-46ea-b2b7-01b630ab12c9-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-fixture-setup.md b/docs/adr/79b476ff-5365-46ea-b2b7-01b630ab12c9-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-fixture-setup.md new file mode 100644 index 000000000000..35cbf4e48325 --- /dev/null +++ b/docs/adr/79b476ff-5365-46ea-b2b7-01b630ab12c9-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-fixture-setup.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Test Fixture Setup + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. SHOULD: Test fixture setup SHOULD use AutoFixture for generating test entities and sutProvider pattern for dependency injection configuration + +## Policy Block + +- SHOULD Test fixture setup SHOULD use AutoFixture for generating test entities and sutProvider pattern for dependency injection configuration + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/79e85707-b8a9-497c-9cdc-d3444434f00d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-use-multiple.md b/docs/adr/79e85707-b8a9-497c-9cdc-d3444434f00d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-use-multiple.md new file mode 100644 index 000000000000..f209d537e2a2 --- /dev/null +++ b/docs/adr/79e85707-b8a9-497c-9cdc-d3444434f00d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-controllers-use-multiple.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Controllers Use Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MAY: Controllers MAY use multiple authorization requirements in sequence (e.g., ManageUsersRequirement followed by resource-specific checks) for layered authorization + +## Policy Block + +- MAY Controllers MAY use multiple authorization requirements in sequence (e.g., ManageUsersRequirement followed by resource-specific checks) for layered authorization + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/7a63602c-8f91-4721-82e4-587068e3f75f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-return.md b/docs/adr/7a63602c-8f91-4721-82e4-587068e3f75f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-return.md new file mode 100644 index 000000000000..799254426511 --- /dev/null +++ b/docs/adr/7a63602c-8f91-4721-82e4-587068e3f75f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-return.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Return + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. SHOULD: FFI functions SHOULD return error codes or null pointers to C callers when input validation fails rather than panicking + +## Policy Block + +- SHOULD FFI functions SHOULD return error codes or null pointers to C callers when input validation fails rather than panicking + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/7a7eb6e8-901b-416d-980b-f0a6b1158259-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-distributed-cache-implementations.md b/docs/adr/7a7eb6e8-901b-416d-980b-f0a6b1158259-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-distributed-cache-implementations.md new file mode 100644 index 000000000000..59a53ae1d56c --- /dev/null +++ b/docs/adr/7a7eb6e8-901b-416d-980b-f0a6b1158259-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-distributed-cache-implementations.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Distributed Cache Implementations + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. MUST: Distributed cache implementations MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client library + +## Policy Block + +- MUST Distributed cache implementations MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client library + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/7b79a03b-7943-44f6-b8a1-5dbcc0ece8b8-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-middleware-added.md b/docs/adr/7b79a03b-7943-44f6-b8a1-5dbcc0ece8b8-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-middleware-added.md new file mode 100644 index 000000000000..7f2868fe860d --- /dev/null +++ b/docs/adr/7b79a03b-7943-44f6-b8a1-5dbcc0ece8b8-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-middleware-added.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authorization Middleware Added + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. MUST: Authorization middleware MUST be added to the request pipeline via app.UseAuthorization() after authentication and before controller routing + +## Policy Block + +- MUST Authorization middleware MUST be added to the request pipeline via app.UseAuthorization() after authentication and before controller routing + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/7c7fbe23-7f8f-4fdd-afdc-b01aa29eac8e-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-cstr-conversions-performed.md b/docs/adr/7c7fbe23-7f8f-4fdd-afdc-b01aa29eac8e-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-cstr-conversions-performed.md new file mode 100644 index 000000000000..b38061993468 --- /dev/null +++ b/docs/adr/7c7fbe23-7f8f-4fdd-afdc-b01aa29eac8e-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-cstr-conversions-performed.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Cstr Conversions Performed + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. MUST: CStr conversions MUST be performed within unsafe blocks with explicit null pointer checks or error handling for invalid UTF-8 sequences + +## Policy Block + +- MUST CStr conversions MUST be performed within unsafe blocks with explicit null pointer checks or error handling for invalid UTF-8 sequences + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/7cfd3bd7-4395-4876-b379-f8b4e676c501-log-redis-connection-failures-in-distributed-cache-extensions-redis-connection-failures.md b/docs/adr/7cfd3bd7-4395-4876-b379-f8b4e676c501-log-redis-connection-failures-in-distributed-cache-extensions-redis-connection-failures.md new file mode 100644 index 000000000000..e17e4ce5565c --- /dev/null +++ b/docs/adr/7cfd3bd7-4395-4876-b379-f8b4e676c501-log-redis-connection-failures-in-distributed-cache-extensions-redis-connection-failures.md @@ -0,0 +1,100 @@ +# Log Redis Connection Failures in Distributed Cache Extensions: Redis Connection Failures + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses StackExchangeRedis as a distributed cache implementation via Microsoft.Extensions.Caching.StackExchangeRedis +- Redis connection establishment occurs in ExtendedCacheServiceCollectionExtensions during service registration, requiring error visibility for operational diagnostics +- The pattern appears in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs where ConnectionMultiplexer.Connect operations are wrapped with structured logging +- Cache initialization failures must be observable to distinguish between configuration errors, network issues, and Redis availability problems + +## Problem Statement + +When Redis connection failures occur during distributed cache initialization, operators and developers need structured, contextual error information to diagnose whether the failure stems from misconfiguration, network connectivity, or Redis service availability, without relying on unhandled exceptions or silent failures. + +## Decision + +1. MUST: Redis connection failures during cache initialization MUST be logged using ILogger.LogError with the exception object and cache name context + +## Policy Block + +- MUST Redis connection failures during cache initialization MUST be logged using ILogger.LogError with the exception object and cache name context + +## Rationale + +- The evidence shows explicit error logging with logger?.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) in ExtendedCacheServiceCollectionExtensions.cs, establishing a pattern of structured error reporting +- Redis connection failures are critical operational events that require immediate visibility, as they directly impact application caching capabilities and performance +- Structured logging with cache name context enables filtering and alerting on specific cache instances in multi-cache deployments +- The pattern uses Microsoft.Extensions.Logging abstractions, ensuring compatibility with various logging providers and observability platforms + +## Consequences + +Positive: +- Operators gain immediate visibility into Redis connection failures through structured logs with contextual information +- Diagnostic time is reduced by including cache name and exception details in a single log entry +- Structured logging parameters enable automated alerting and filtering in log aggregation systems +- The pattern integrates with existing Microsoft.Extensions.Logging infrastructure without additional dependencies + +Negative: +- Log volume increases during Redis outages or misconfigurations, potentially impacting log storage costs +- Sensitive connection string information must be carefully sanitized to avoid credential leakage in logs +- The null-conditional operator (logger?) allows silent failures if logging is not configured, reducing error visibility + +## Alternatives + +- Allow ConnectionMultiplexer.Connect exceptions to propagate unhandled, relying on global exception handlers (rejected) + Rejected because: Unhandled exceptions during service registration cause application startup failures without contextual information about which cache failed or why + When valid: In scenarios where fail-fast behavior is required and any cache initialization failure should prevent application startup +- Use health checks to detect Redis connectivity issues post-startup rather than logging during initialization (rejected) + Rejected because: Health checks provide runtime monitoring but do not capture initialization-time failures or provide immediate diagnostic context during startup + When valid: As a complementary approach for ongoing runtime monitoring after successful initialization +- Implement retry logic with exponential backoff before logging connection failures (deferred) + Rejected because: Retry logic adds complexity and startup latency; the current pattern focuses on observability rather than resilience + When valid: When transient network issues are common and automatic recovery is preferred over immediate failure reporting + +## Risks + +- Connection string credentials may be inadvertently logged if error messages include full connection details + Mitigation: Sanitize connection strings before logging and rely on structured parameters that exclude sensitive data + Owner: engineering team +- The null-conditional operator (logger?) allows silent failures when ILogger is not injected or configured + Mitigation: Ensure logging infrastructure is configured before cache service registration or use non-null logger instances + Owner: engineering team +- High-frequency connection failures during Redis outages may generate excessive log volume + Mitigation: Implement log rate limiting or circuit breaker patterns for repeated connection attempts + Owner: operations team + +## Implementation Notes + +- Wrap ConnectionMultiplexer.Connect calls in try-catch blocks within cache service registration extensions +- Use ILogger.LogError with the exception as the first parameter and structured logging syntax for cache name: logger.LogError(ex, "Failed to connect to Redis for cache {CacheName}", cacheName) +- Ensure ILogger instances are injected into service collection extension methods via IServiceProvider or factory patterns +- Consider adding correlation IDs or request context to error logs for distributed tracing integration + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*Failed to connect to Redis' src/ +- grep -r 'ConnectionMultiplexer\.Connect' src/ | grep -c 'try\|catch' +- dotnet test --filter Category=CacheInitialization --logger "console;verbosity=detailed" + +Accept when: +- All Redis connection attempts in cache service registration extensions are wrapped with try-catch blocks that log errors using ILogger.LogError +- Error log statements include structured parameters for cache name and exception details +- Unit tests verify that connection failures produce expected log entries with correct log levels and parameters + +## Enforcement + +- Verified by: Code review checklist requiring error logging for all external service connections +- Verified by: Static analysis rules detecting ConnectionMultiplexer.Connect calls without surrounding try-catch blocks +- Verified by: Integration tests that simulate Redis connection failures and assert expected log output +- Violation handling: Pull requests introducing cache initialization code without error logging are flagged during code review +- Violation handling: Static analysis warnings are treated as build failures in CI pipeline +- Violation handling: Production incidents involving unlogged cache failures trigger retrospective reviews and pattern reinforcement +- Exception process: Exceptions require architectural review approval with documented justification +- Exception process: Alternative observability mechanisms (e.g., metrics, tracing) must be demonstrated +- Exception process: Exception approvals are time-limited and require renewal during annual architecture reviews \ No newline at end of file diff --git a/docs/adr/7e79fd2f-f710-4f04-9d12-f46135302205-establish-http-client-boundaries-for-external-service-integration-external-client-calls.md b/docs/adr/7e79fd2f-f710-4f04-9d12-f46135302205-establish-http-client-boundaries-for-external-service-integration-external-client-calls.md new file mode 100644 index 000000000000..6c9db1632471 --- /dev/null +++ b/docs/adr/7e79fd2f-f710-4f04-9d12-f46135302205-establish-http-client-boundaries-for-external-service-integration-external-client-calls.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: External Client Calls + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. SHOULD: External client calls SHOULD use async/await patterns (Server.GetAsync, Server.PostAsync, Server.PutAsync, Server.PatchAsync) to prevent thread pool exhaustion + +## Policy Block + +- SHOULD External client calls SHOULD use async/await patterns (Server.GetAsync, Server.PostAsync, Server.PutAsync, Server.PatchAsync) to prevent thread pool exhaustion + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/7ee91a40-96b5-4068-9cbc-bfa50d5641ac-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-failures-throw.md b/docs/adr/7ee91a40-96b5-4068-9cbc-bfa50d5641ac-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-failures-throw.md new file mode 100644 index 000000000000..9e7ec2866f92 --- /dev/null +++ b/docs/adr/7ee91a40-96b5-4068-9cbc-bfa50d5641ac-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-failures-throw.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Authorization Failures Throw + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. MUST: Authorization failures MUST throw NotFoundException or UnauthorizedAccessException to prevent information disclosure about protected resources + +## Policy Block + +- MUST Authorization failures MUST throw NotFoundException or UnauthorizedAccessException to prevent information disclosure about protected resources + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/7fee142b-06b9-432b-81ec-911cb732b053-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-requiring.md b/docs/adr/7fee142b-06b9-432b-81ec-911cb732b053-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-requiring.md new file mode 100644 index 000000000000..a7c364e88c6f --- /dev/null +++ b/docs/adr/7fee142b-06b9-432b-81ec-911cb732b053-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-code-requiring.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Code Requiring + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. MUST: Test code requiring RSA key fixtures MUST use embedded string constants containing PEM-encoded private keys rather than generating keys at runtime or loading from external files + +## Policy Block + +- MUST Test code requiring RSA key fixtures MUST use embedded string constants containing PEM-encoded private keys rather than generating keys at runtime or loading from external files + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/80d4fa0c-c256-4ad8-be81-9dd26277d7de-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-context-classes-include.md b/docs/adr/80d4fa0c-c256-4ad8-be81-9dd26277d7de-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-context-classes-include.md new file mode 100644 index 000000000000..63bf0c1752e4 --- /dev/null +++ b/docs/adr/80d4fa0c-c256-4ad8-be81-9dd26277d7de-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-context-classes-include.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Context Classes Include + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. MAY: Context classes MAY include configuration methods (OnModelCreating) to define entity relationships, keys, and database-specific behaviors + +## Policy Block + +- MAY Context classes MAY include configuration methods (OnModelCreating) to define entity relationships, keys, and database-specific behaviors + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/8303fcd7-1b32-4ea7-a6c0-a42d3079eac9-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-types-cipher.md b/docs/adr/8303fcd7-1b32-4ea7-a6c0-a42d3079eac9-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-types-cipher.md new file mode 100644 index 000000000000..3d6127f7a3d0 --- /dev/null +++ b/docs/adr/8303fcd7-1b32-4ea7-a6c0-a42d3079eac9-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-types-cipher.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Cryptographic Types Cipher + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. SHOULD: Cryptographic types (cipher, SymmetricCryptoKey, RSA_POOL) SHOULD be encapsulated behind opaque pointers when exposed through FFI + +## Policy Block + +- SHOULD Cryptographic types (cipher, SymmetricCryptoKey, RSA_POOL) SHOULD be encapsulated behind opaque pointers when exposed through FFI + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/8332d4f6-d878-4891-85f3-f261cf790c5f-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-types.md b/docs/adr/8332d4f6-d878-4891-85f3-f261cf790c5f-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-types.md new file mode 100644 index 000000000000..59fd20a6cad1 --- /dev/null +++ b/docs/adr/8332d4f6-d878-4891-85f3-f261cf790c5f-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-custom-result-types.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Custom Result Types + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. MUST: Custom result types that wrap framework results MUST delegate ExecuteAsync to the inner result implementation + +## Policy Block + +- MUST Custom result types that wrap framework results MUST delegate ExecuteAsync to the inner result implementation + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/846bc329-4589-4607-9efd-6033c355563a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-use.md b/docs/adr/846bc329-4589-4607-9efd-6033c355563a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-use.md new file mode 100644 index 000000000000..267605b56285 --- /dev/null +++ b/docs/adr/846bc329-4589-4607-9efd-6033c355563a-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-use.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. MAY: FFI functions MAY use std::panic::catch_unwind to prevent panics from crossing FFI boundaries + +## Policy Block + +- MAY FFI functions MAY use std::panic::catch_unwind to prevent panics from crossing FFI boundaries + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/859c13ba-4abb-4b8d-85ce-aac9e8f13ed5-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-distributed-caching-implementations.md b/docs/adr/859c13ba-4abb-4b8d-85ce-aac9e8f13ed5-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-distributed-caching-implementations.md new file mode 100644 index 000000000000..314be9fb53c8 --- /dev/null +++ b/docs/adr/859c13ba-4abb-4b8d-85ce-aac9e8f13ed5-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-distributed-caching-implementations.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Distributed Caching Implementations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. MUST: Distributed caching implementations MUST use Microsoft.Extensions.Caching.Distributed abstractions (IDistributedCache) rather than direct Redis client dependencies + +## Policy Block + +- MUST Distributed caching implementations MUST use Microsoft.Extensions.Caching.Distributed abstractions (IDistributedCache) rather than direct Redis client dependencies + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/86b1ddae-ffa0-4f45-8f93-0ab9ec630cc8-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-properties-organized.md b/docs/adr/86b1ddae-ffa0-4f45-8f93-0ab9ec630cc8-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-properties-organized.md new file mode 100644 index 000000000000..74cc320570aa --- /dev/null +++ b/docs/adr/86b1ddae-ffa0-4f45-8f93-0ab9ec630cc8-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-dbset-properties-organized.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Dbset Properties Organized + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. SHOULD: DbSet properties SHOULD be organized by domain area or functional grouping within the context class to improve readability + +## Policy Block + +- SHOULD DbSet properties SHOULD be organized by domain area or functional grouping within the context class to improve readability + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/87be164b-bd95-43a3-ae40-6f0fa34ced4a-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-validate.md b/docs/adr/87be164b-bd95-43a3-ae40-6f0fa34ced4a-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-validate.md new file mode 100644 index 000000000000..5f410547c892 --- /dev/null +++ b/docs/adr/87be164b-bd95-43a3-ae40-6f0fa34ced4a-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-functions-validate.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Functions Validate + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. MUST: FFI functions MUST validate that c_char pointers are non-null before dereferencing or converting to CStr + +## Policy Block + +- MUST FFI functions MUST validate that c_char pointers are non-null before dereferencing or converting to CStr + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/889fa803-9d10-47fd-8fa5-96a0dd4899e7-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-each-fake-rsa.md b/docs/adr/889fa803-9d10-47fd-8fa5-96a0dd4899e7-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-each-fake-rsa.md new file mode 100644 index 000000000000..2ca48a8a22e6 --- /dev/null +++ b/docs/adr/889fa803-9d10-47fd-8fa5-96a0dd4899e7-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-each-fake-rsa.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Each Fake Rsa + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. MUST: Each fake RSA key constant MUST contain a complete PEM-encoded private key block including BEGIN PRIVATE KEY and END PRIVATE KEY markers + +## Policy Block + +- MUST Each fake RSA key constant MUST contain a complete PEM-encoded private key block including BEGIN PRIVATE KEY and END PRIVATE KEY markers + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/893a7c18-91d2-4ec7-b446-5ad2251fa57d-validate-ffi-input-using-rust-type-system-and-c-string-conversions-cryptographic-key-material.md b/docs/adr/893a7c18-91d2-4ec7-b446-5ad2251fa57d-validate-ffi-input-using-rust-type-system-and-c-string-conversions-cryptographic-key-material.md new file mode 100644 index 000000000000..8873c4fc123a --- /dev/null +++ b/docs/adr/893a7c18-91d2-4ec7-b446-5ad2251fa57d-validate-ffi-input-using-rust-type-system-and-c-string-conversions-cryptographic-key-material.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Cryptographic Key Material + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. MUST: Cryptographic key material received via FFI MUST be validated for format correctness (e.g., PEM structure) before passing to bitwarden_crypto operations + +## Policy Block + +- MUST Cryptographic key material received via FFI MUST be validated for format correctness (e.g., PEM structure) before passing to bitwarden_crypto operations + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/8bf3971d-2183-4106-bb02-1d737379e42a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-validate-operation.md b/docs/adr/8bf3971d-2183-4106-bb02-1d737379e42a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-validate-operation.md new file mode 100644 index 000000000000..9f96404dd97e --- /dev/null +++ b/docs/adr/8bf3971d-2183-4106-bb02-1d737379e42a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-validate-operation.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Validate Operation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. MUST: Tests MUST validate operation classification (AccessPolicyOperation.Create, Update, Delete) in query results to ensure correct coordination logic + +## Policy Block + +- MUST Tests MUST validate operation classification (AccessPolicyOperation.Create, Update, Delete) in query results to ensure correct coordination logic + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/8c53f1bd-3055-4879-a45c-7be3e98c1a96-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-csbindgen-configuration-specify.md b/docs/adr/8c53f1bd-3055-4879-a45c-7be3e98c1a96-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-csbindgen-configuration-specify.md new file mode 100644 index 000000000000..4fc32962aad4 --- /dev/null +++ b/docs/adr/8c53f1bd-3055-4879-a45c-7be3e98c1a96-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-csbindgen-configuration-specify.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Csbindgen Configuration Specify + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. SHOULD: The csbindgen configuration SHOULD specify the native library name (csharp_dll_name) to match the compiled Rust artifact. + +## Policy Block + +- SHOULD The csbindgen configuration SHOULD specify the native library name (csharp_dll_name) to match the compiled Rust artifact. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/8ed82d97-4d70-4553-988f-f79331b9ef22-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-handling-external.md b/docs/adr/8ed82d97-4d70-4553-988f-f79331b9ef22-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-handling-external.md new file mode 100644 index 000000000000..6f425e4f8cf9 --- /dev/null +++ b/docs/adr/8ed82d97-4d70-4553-988f-f79331b9ef22-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-controllers-handling-external.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Controllers Handling External + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. SHOULD: Controllers handling external service calls within authorized contexts SHOULD log both the failure and the partial success state to support audit and rollback analysis + +## Policy Block + +- SHOULD Controllers handling external service calls within authorized contexts SHOULD log both the failure and the partial success state to support audit and rollback analysis + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/8ef3fe32-3e55-45e5-9b27-56d1ca7de403-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-types-requiring.md b/docs/adr/8ef3fe32-3e55-45e5-9b27-56d1ca7de403-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-types-requiring.md new file mode 100644 index 000000000000..0eaaa17cddbb --- /dev/null +++ b/docs/adr/8ef3fe32-3e55-45e5-9b27-56d1ca7de403-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-types-requiring.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Entity Types Requiring + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. MUST: All entity types requiring database persistence MUST be registered as DbSet properties in the primary DatabaseContext class + +## Policy Block + +- MUST All entity types requiring database persistence MUST be registered as DbSet properties in the primary DatabaseContext class + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/8f6f9141-ac0c-48f6-8d5e-02b7e6a25e43-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-combine-multiple.md b/docs/adr/8f6f9141-ac0c-48f6-8d5e-02b7e6a25e43-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-combine-multiple.md new file mode 100644 index 000000000000..2a8242844f7d --- /dev/null +++ b/docs/adr/8f6f9141-ac0c-48f6-8d5e-02b7e6a25e43-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controllers-combine-multiple.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controllers Combine Multiple + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. MAY: Controllers MAY combine multiple authorization attributes on a single action method when multiple authorization policies must be satisfied + +## Policy Block + +- MAY Controllers MAY combine multiple authorization attributes on a single action method when multiple authorization policies must be satisfied + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/8f9885e8-0c25-422f-9a77-cf407a73f7b0-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-unit-tests-query.md b/docs/adr/8f9885e8-0c25-422f-9a77-cf407a73f7b0-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-unit-tests-query.md new file mode 100644 index 000000000000..d63cd602a79d --- /dev/null +++ b/docs/adr/8f9885e8-0c25-422f-9a77-cf407a73f7b0-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-unit-tests-query.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Unit Tests Query + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. MUST: Unit tests for query classes MUST invoke the system under test through its public interface method (e.g., GetAsync) and verify results without direct access to internal state + +## Policy Block + +- MUST Unit tests for query classes MUST invoke the system under test through its public interface method (e.g., GetAsync) and verify results without direct access to internal state + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/910fe798-7802-4a1e-9329-07007b1ea997-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md b/docs/adr/910fe798-7802-4a1e-9329-07007b1ea997-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md new file mode 100644 index 000000000000..c00489404916 --- /dev/null +++ b/docs/adr/910fe798-7802-4a1e-9329-07007b1ea997-verify-logger-invocations-in-unit-tests-for-observability-components-logger-verification-use.md @@ -0,0 +1,116 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Logger Verification Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Unit tests in the codebase verify that logger dependencies are invoked with expected warning messages during error conditions +- The pattern appears in test files for SCIM group operations (PatchGroupCommandTests.cs) and authentication request services (AuthRequestServiceTests.cs) +- Tests use dependency injection providers to retrieve ILogger instances and assert that specific log methods (LogWarning) are called with exact message strings +- This testing approach treats logging as a verifiable behavior rather than an implementation detail, ensuring observability contracts are maintained + +## Problem Statement + +Without explicit verification of logging behavior in unit tests, critical diagnostic messages may be removed or modified during refactoring, degrading operational observability and making production issues harder to diagnose. The codebase needs a consistent approach to ensure logging contracts are tested alongside business logic. + +## Decision + +1. SHOULD: Logger verification SHOULD use ReceivedWithAnyArgs() when the exact message parameters are not critical to the test assertion + +## Policy Block + +- SHOULD Logger verification SHOULD use ReceivedWithAnyArgs() when the exact message parameters are not critical to the test assertion + +In scope: +- Unit tests for services and commands that include ILogger dependencies +- Test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected +- Components in the Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging + +Out of scope: +- Integration tests where actual logging infrastructure is used rather than mocked +- Performance tests where logger verification overhead is unacceptable +- Tests for components that do not have logging dependencies +- Logging infrastructure implementation tests (e.g., testing the logger itself) + +Exceptions: +- EX-001: The logging behavior is purely diagnostic and not part of any operational contract or alerting logic + +## Rationale + +- The evidence shows 2 test files explicitly verifying ILogger invocations with specific messages, indicating an established pattern for treating logging as testable behavior +- Verifying logger calls ensures that operational observability contracts are maintained across refactoring and code changes +- The pattern uses dependency injection and mocking frameworks (AutoFixture, NSubstitute) already present in the codebase, requiring no additional infrastructure +- Testing logging behavior provides early detection of changes that could impact production diagnostics and incident response + +## Consequences + +Positive: +- Logging contracts become explicit and protected by automated tests, preventing silent degradation of observability +- Developers receive immediate feedback when refactoring removes or changes critical diagnostic messages +- The pattern integrates naturally with existing dependency injection and unit testing infrastructure +- Production incident response is improved through guaranteed availability of expected log messages + +Negative: +- Unit tests become coupled to logging implementation details, potentially increasing test maintenance burden +- Test verbosity increases as logger verification adds additional assertions to each test case +- Refactoring log messages requires updating corresponding test assertions, slowing down minor message improvements +- Over-specification of logging behavior may discourage developers from adding helpful diagnostic logging + +## Alternatives + +- Treat logging as an implementation detail and do not verify logger invocations in unit tests (rejected) + Rejected because: This approach allows critical diagnostic messages to be removed during refactoring without detection, degrading production observability. The evidence shows the codebase has already adopted explicit logger verification. + When valid: For purely diagnostic logging that has no operational significance and is not used for alerting or incident response +- Use integration tests with actual logging infrastructure to verify log output (deferred) + Rejected because: Integration tests provide slower feedback and higher maintenance cost. This approach complements rather than replaces unit-level verification. + When valid: For end-to-end validation of logging configuration, formatting, and sink behavior in staging environments +- Implement custom logging abstractions that separate testable events from log formatting (rejected) + Rejected because: This requires significant infrastructure changes and abstracts away the ILogger pattern already established in the codebase. The current approach works with existing dependencies. + When valid: For greenfield projects or major logging infrastructure redesigns where decoupling events from formatting provides clear architectural benefits + +## Risks + +- Over-specification of log messages in tests creates brittleness, where minor message improvements require widespread test updates + Mitigation: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules + Owner: Engineering team +- Developers may avoid adding helpful logging to avoid increasing test complexity and maintenance burden + Mitigation: Establish clear guidelines on which logging calls require verification (error conditions, security events, operational alerts) versus which are purely diagnostic + Owner: Engineering team and tech leads +- Logger verification may not catch issues with log message formatting, structured logging parameters, or sink configuration + Mitigation: Complement unit-level logger verification with integration tests that validate actual log output in representative environments + Owner: QA and engineering team + +## Implementation Notes + +- Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure +- Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.) +- Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract +- Document in test comments when logger verification is intentionally omitted for purely diagnostic logging +- Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns + +## Continuation Context + + +Verify commands: +- grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts + +## Enforcement + +- Verified by: Code review checks for logger verification in unit tests covering error conditions and operational events +- Verified by: CI pipeline runs unit tests that include logger verification assertions +- Verified by: Static analysis or custom linting rules to detect ILogger dependencies without corresponding test verification +- Violation handling: Code review feedback requests addition of logger verification for components with ILogger dependencies +- Violation handling: Pull requests may be blocked if critical error paths lack logging verification +- Violation handling: Retrospective analysis of production incidents identifies missing logging that should have been tested +- Exception process: Developer documents in test comments why logger verification is omitted (e.g., purely diagnostic logging) +- Exception process: Team lead approves exception during code review based on operational significance assessment +- Exception process: Exception is recorded in test file comments for future reference \ No newline at end of file diff --git a/docs/adr/916751b2-b271-443c-9795-004adff9f00b-enforce-authorization-service-pattern-for-access-control-decisions-test-environments-use.md b/docs/adr/916751b2-b271-443c-9795-004adff9f00b-enforce-authorization-service-pattern-for-access-control-decisions-test-environments-use.md new file mode 100644 index 000000000000..5605c0c89f6e --- /dev/null +++ b/docs/adr/916751b2-b271-443c-9795-004adff9f00b-enforce-authorization-service-pattern-for-access-control-decisions-test-environments-use.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Test Environments Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MAY: Test environments MAY use custom AuthenticationHandler implementations (e.g., TestAuthHandler) to simulate authentication for integration testing + +## Policy Block + +- MAY Test environments MAY use custom AuthenticationHandler implementations (e.g., TestAuthHandler) to simulate authentication for integration testing + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/918af20b-0276-447f-88f2-b10ecc4f55a9-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-boundary-functions.md b/docs/adr/918af20b-0276-447f-88f2-b10ecc4f55a9-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-boundary-functions.md new file mode 100644 index 000000000000..f47f8913c687 --- /dev/null +++ b/docs/adr/918af20b-0276-447f-88f2-b10ecc4f55a9-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-boundary-functions.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Ffi Boundary Functions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. SHOULD: FFI boundary functions SHOULD use std::ffi types exclusively for C interoperability rather than custom pointer wrappers + +## Policy Block + +- SHOULD FFI boundary functions SHOULD use std::ffi types exclusively for C interoperability rather than custom pointer wrappers + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/925c710e-4e51-42f8-8fc3-06b61c142cdd-standardize-authorization-policy-configuration-with-named-scopes-authorization-configuration-applied.md b/docs/adr/925c710e-4e51-42f8-8fc3-06b61c142cdd-standardize-authorization-policy-configuration-with-named-scopes-authorization-configuration-applied.md new file mode 100644 index 000000000000..d9764126a801 --- /dev/null +++ b/docs/adr/925c710e-4e51-42f8-8fc3-06b61c142cdd-standardize-authorization-policy-configuration-with-named-scopes-authorization-configuration-applied.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authorization Configuration Applied + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. MUST: Authorization configuration MUST be applied in the ConfigureServices method before middleware pipeline configuration + +## Policy Block + +- MUST Authorization configuration MUST be applied in the ConfigureServices method before middleware pipeline configuration + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/92c03b28-7ea3-46c3-aa8f-b89cb67bcb9b-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-implementations-use.md b/docs/adr/92c03b28-7ea3-46c3-aa8f-b89cb67bcb9b-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-implementations-use.md new file mode 100644 index 000000000000..a0b3c7760522 --- /dev/null +++ b/docs/adr/92c03b28-7ea3-46c3-aa8f-b89cb67bcb9b-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-implementations-use.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Cache Implementations Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. SHOULD: Cache implementations SHOULD use TryAdd patterns (e.g., TryAddSingleton) from Microsoft.Extensions.DependencyInjection.Extensions to avoid duplicate registrations + +## Policy Block + +- SHOULD Cache implementations SHOULD use TryAdd patterns (e.g., TryAddSingleton) from Microsoft.Extensions.DependencyInjection.Extensions to avoid duplicate registrations + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/93330207-06c0-4452-9a7a-8d3d66685272-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-modules-document.md b/docs/adr/93330207-06c0-4452-9a7a-8d3d66685272-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-modules-document.md new file mode 100644 index 000000000000..83bec24474cf --- /dev/null +++ b/docs/adr/93330207-06c0-4452-9a7a-8d3d66685272-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-modules-document.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Modules Document + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. SHOULD: FFI modules SHOULD document the expected string encoding (UTF-8) and null-termination requirements in function signatures + +## Policy Block + +- SHOULD FFI modules SHOULD document the expected string encoding (UTF-8) and null-termination requirements in function signatures + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/93ca6910-d73c-400a-9049-65abe6c60978-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-key-types.md b/docs/adr/93ca6910-d73c-400a-9049-65abe6c60978-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-key-types.md new file mode 100644 index 000000000000..4e2b92936412 --- /dev/null +++ b/docs/adr/93ca6910-d73c-400a-9049-65abe6c60978-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-key-types.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Cryptographic Key Types + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. MUST: All cryptographic key types (cipher, rsa_keys, SymmetricCryptoKey) MUST be modeled as distinct data structures with explicit FFI-safe representations using std::ffi types (c_char, CStr, CString) + +## Policy Block + +- MUST All cryptographic key types (cipher, rsa_keys, SymmetricCryptoKey) MUST be modeled as distinct data structures with explicit FFI-safe representations using std::ffi types (c_char, CStr, CString) + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/94d3fff7-cc0a-47a0-bd13-0d957a5de9fb-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-policies-registered.md b/docs/adr/94d3fff7-cc0a-47a0-bd13-0d957a5de9fb-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-policies-registered.md new file mode 100644 index 000000000000..e430f57f4ff8 --- /dev/null +++ b/docs/adr/94d3fff7-cc0a-47a0-bd13-0d957a5de9fb-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-policies-registered.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Authorization Policies Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. SHOULD: Authorization policies SHOULD be registered in service configuration using AddAuthorization with named policies or requirement types + +## Policy Block + +- SHOULD Authorization policies SHOULD be registered in service configuration using AddAuthorization with named policies or requirement types + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/94de471a-d3c3-4311-9187-13e91cebe0f2-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-exception-handling-tests.md b/docs/adr/94de471a-d3c3-4311-9187-13e91cebe0f2-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-exception-handling-tests.md new file mode 100644 index 000000000000..c032fd898bce --- /dev/null +++ b/docs/adr/94de471a-d3c3-4311-9187-13e91cebe0f2-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-exception-handling-tests.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Exception Handling Tests + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. SHOULD: Exception handling tests SHOULD verify that queries throw expected exceptions (NotFoundException) when external dependencies return invalid state + +## Policy Block + +- SHOULD Exception handling tests SHOULD verify that queries throw expected exceptions (NotFoundException) when external dependencies return invalid state + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/9595cb10-0420-4f1a-8b54-84969f09ad4d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-endpoints-modifying-collection.md b/docs/adr/9595cb10-0420-4f1a-8b54-84969f09ad4d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-endpoints-modifying-collection.md new file mode 100644 index 000000000000..655dd15f787b --- /dev/null +++ b/docs/adr/9595cb10-0420-4f1a-8b54-84969f09ad4d-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-endpoints-modifying-collection.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Endpoints Modifying Collection + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MUST: Endpoints modifying collection access for users MUST call AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess requirement before persisting changes + +## Policy Block + +- MUST Endpoints modifying collection access for users MUST call AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess requirement before persisting changes + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/95a40c26-775a-4a73-b44e-6fc159188177-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-generated-bindings-specify.md b/docs/adr/95a40c26-775a-4a73-b44e-6fc159188177-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-generated-bindings-specify.md new file mode 100644 index 000000000000..f0865486dcf0 --- /dev/null +++ b/docs/adr/95a40c26-775a-4a73-b44e-6fc159188177-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-generated-bindings-specify.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Generated Bindings Specify + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. MUST: Generated C# bindings MUST specify a consistent namespace (e.g., Bit.RustSDK) and public class accessibility for consumer access. + +## Policy Block + +- MUST Generated C# bindings MUST specify a consistent namespace (e.g., Bit.RustSDK) and public class accessibility for consumer access. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/95a61a86-bb62-4b1a-8d77-320971142c14-expose-extended-cache-configuration-as-public-api-contract-services-extend-base.md b/docs/adr/95a61a86-bb62-4b1a-8d77-320971142c14-expose-extended-cache-configuration-as-public-api-contract-services-extend-base.md new file mode 100644 index 000000000000..f0dd2d09fe23 --- /dev/null +++ b/docs/adr/95a61a86-bb62-4b1a-8d77-320971142c14-expose-extended-cache-configuration-as-public-api-contract-services-extend-base.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Services Extend Base + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. MAY: Services MAY extend the base ExtendedCacheServiceCollectionExtensions with additional cache-specific configuration options + +## Policy Block + +- MAY Services MAY extend the base ExtendedCacheServiceCollectionExtensions with additional cache-specific configuration options + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/98164f52-434e-46c9-af87-18909877ff3f-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-authorization-policies.md b/docs/adr/98164f52-434e-46c9-af87-18909877ff3f-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-authorization-policies.md new file mode 100644 index 000000000000..a9eb511a1287 --- /dev/null +++ b/docs/adr/98164f52-434e-46c9-af87-18909877ff3f-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-authorization-policies.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Authorization Policies + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. SHOULD: Test authorization policies SHOULD use RequireAssertion for flexible test scenario configuration + +## Policy Block + +- SHOULD Test authorization policies SHOULD use RequireAssertion for flexible test scenario configuration + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/981f8aa3-70d1-4704-b00a-242fa78bbfa2-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md b/docs/adr/981f8aa3-70d1-4704-b00a-242fa78bbfa2-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md new file mode 100644 index 000000000000..18bd36d8cd99 --- /dev/null +++ b/docs/adr/981f8aa3-70d1-4704-b00a-242fa78bbfa2-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-controller-action-methods.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Controller Action Methods + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. MUST: All controller action methods that require authorization MUST declare authorization requirements using the Authorize attribute with a specific requirement type (e.g., Authorize) + +## Policy Block + +- MUST All controller action methods that require authorization MUST declare authorization requirements using the Authorize attribute with a specific requirement type (e.g., Authorize) + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/9860d08f-ad1a-48b1-8d99-3c3dfff6f9c7-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-self-modification-operations.md b/docs/adr/9860d08f-ad1a-48b1-8d99-3c3dfff6f9c7-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-self-modification-operations.md new file mode 100644 index 000000000000..801b9e29b3b3 --- /dev/null +++ b/docs/adr/9860d08f-ad1a-48b1-8d99-3c3dfff6f9c7-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-self-modification-operations.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Self Modification Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MUST: Self-modification operations MUST check organizationAbility.AllowAdminAccessToAllCollectionItems before permitting users to add themselves to collections or groups + +## Policy Block + +- MUST Self-modification operations MUST check organizationAbility.AllowAdminAccessToAllCollectionItems before permitting users to add themselves to collections or groups + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/9899c5f7-96f5-47d3-824a-880f38e2b5ff-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-authorization-attributes-applied.md b/docs/adr/9899c5f7-96f5-47d3-824a-880f38e2b5ff-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-authorization-attributes-applied.md new file mode 100644 index 000000000000..850212595adc --- /dev/null +++ b/docs/adr/9899c5f7-96f5-47d3-824a-880f38e2b5ff-adopt-attribute-based-authorization-model-for-asp-net-core-controllers-authorization-attributes-applied.md @@ -0,0 +1,123 @@ +# Adopt Attribute-Based Authorization Model for ASP.NET Core Controllers: Authorization Attributes Applied + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all ASP.NET Core controller implementations within the AdminConsole and Admin API surfaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase uses ASP.NET Core's attribute-based authorization model with custom generic Authorize attributes (e.g., Authorize, Authorize) applied directly to controller action methods +- Authorization decisions are declaratively expressed at the method level rather than imperatively checked within method bodies, separating authorization concerns from business logic +- The pattern appears across multiple controller classes in both Api.AdminConsole and Admin namespaces, indicating a standardized approach to access control across administrative surfaces +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) are used alongside the generic Authorize attribute, suggesting a requirement-based authorization policy system + +## Problem Statement + +ASP.NET Core applications require a consistent, maintainable approach to enforcing authorization rules across HTTP endpoints. Without a standardized authorization model, access control logic becomes scattered across controller methods, difficult to audit, and prone to inconsistent enforcement. The system needs a declarative mechanism that makes authorization requirements explicit, testable, and separate from business logic. + +## Decision + +1. MUST: Authorization attributes MUST be applied at the method level to make per-endpoint authorization requirements explicit and auditable + +## Policy Block + +- MUST Authorization attributes MUST be applied at the method level to make per-endpoint authorization requirements explicit and auditable + +In scope: +- All ASP.NET Core MVC and API controllers in the Api.AdminConsole namespace +- All ASP.NET Core MVC controllers in the Admin namespace +- HTTP action methods (GET, POST, PUT, DELETE) that require authenticated or role-based access +- Custom authorization requirement types defined in Bit.Api.AdminConsole.Authorization namespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous +- Middleware-level authorization logic +- Authorization handlers that implement the requirement evaluation logic +- Non-HTTP service layer authorization checks + +Exceptions: +- EXC-001: Legacy endpoints that require complex, multi-step authorization logic that cannot be expressed declaratively may implement imperative authorization checks +- EXC-002: Token-based public endpoints (e.g., invite links) may use AllowAnonymous with imperative token validation within the method body + +## Rationale + +- The evidence shows consistent use of Authorize attributes across 4 controller files with 78.97% confidence, indicating an established architectural pattern rather than isolated usage +- Declarative authorization via attributes provides compile-time visibility of access control requirements and enables centralized policy enforcement through ASP.NET Core's authorization middleware +- Separating authorization concerns from business logic improves testability, as authorization policies can be tested independently from controller action logic +- The pattern aligns with ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom infrastructure and leveraging framework-provided security features + +## Consequences + +Positive: +- Authorization requirements are immediately visible when reading controller code, improving security auditability and code comprehension +- Centralized authorization policy evaluation through ASP.NET Core middleware ensures consistent enforcement across all endpoints +- Testability improves as authorization logic is separated from business logic and can be tested through policy-based unit tests +- Framework integration provides automatic HTTP 401/403 responses for authorization failures without custom error handling code + +Negative: +- Complex authorization scenarios requiring multiple contextual checks may be difficult to express purely through declarative attributes +- Generic Authorize syntax may be unfamiliar to developers accustomed to role-based or policy-name string attributes +- Authorization requirement types proliferate as new access control patterns emerge, requiring maintenance of requirement classes and handlers +- Debugging authorization failures requires understanding the middleware pipeline and handler execution order, which is less transparent than imperative checks + +## Alternatives + +- Use imperative authorization checks within controller action methods via IAuthorizationService.AuthorizeAsync() (rejected) + Rejected because: Imperative checks scatter authorization logic across controller methods, making it difficult to audit access control requirements and increasing the risk of inconsistent enforcement + When valid: Valid for complex, multi-step authorization scenarios that cannot be expressed declaratively or require dynamic policy composition based on request data +- Use string-based policy names with [Authorize(Policy = "PolicyName")] instead of generic requirement types (rejected) + Rejected because: String-based policy names lack compile-time safety and make it harder to discover which policies exist and where they are used without full-text search + When valid: Valid for simple role-based or claim-based policies that do not require custom requirement types +- Apply authorization attributes at the controller class level for uniform endpoint protection (rejected) + Rejected because: Class-level attributes hide per-endpoint authorization requirements and make it difficult to identify which specific actions have different authorization needs + When valid: Valid when all actions in a controller genuinely require identical authorization and no action-specific requirements exist + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated verification that scans controller actions for missing authorization attributes and fails CI builds when unprotected endpoints are detected + Owner: Security Engineering Team +- Complex authorization requirements may be incorrectly simplified into declarative attributes, weakening access control + Mitigation: Establish clear guidelines for when imperative authorization is acceptable and require security review for authorization handler implementations + Owner: Application Security Team +- Authorization requirement types may be reused inappropriately across different contexts, leading to over-permissive access + Mitigation: Name requirement types specifically for their intended use case and document the authorization semantics in XML comments on the requirement class + Owner: Engineering Team + +## Implementation Notes + +- Define custom authorization requirement types in a dedicated Authorization namespace (e.g., Bit.Api.AdminConsole.Authorization.Requirements) to centralize authorization concerns +- Implement IAuthorizationHandler for each custom requirement type to encapsulate the authorization evaluation logic +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use descriptive requirement type names that clearly communicate the authorization intent (e.g., ManageUsersRequirement, ProviderAdminRequirement) +- For endpoints that intentionally allow anonymous access, explicitly apply [AllowAnonymous] to document the decision and prevent accidental protection + +## Continuation Context + + +Verify commands: +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Controllers src/Admin/Controllers -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods in AdminConsole and Admin namespaces have either [Authorize] or [AllowAnonymous] attributes +- No controller action methods contain imperative authorization checks (IAuthorizationService.AuthorizeAsync calls) for requirements that can be expressed declaratively +- Authorization requirement types are defined in dedicated Authorization namespaces and have corresponding handler implementations registered in DI + +## Enforcement + +- Verified by: Automated static analysis scanning controller methods for missing authorization attributes during CI builds +- Verified by: Code review checklist requiring verification that new controller actions have appropriate authorization attributes +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI build fails if controller actions lack authorization attributes and are not explicitly marked as public +- Violation handling: Pull requests with authorization violations are blocked from merge until attributes are added or exceptions are documented +- Violation handling: Security team is notified of authorization attribute violations detected in production code +- Exception process: Developer documents why declarative authorization is insufficient for the specific endpoint +- Exception process: Security team reviews the imperative authorization implementation for correctness and completeness +- Exception process: Exception is recorded in code comments with a reference to the security review approval +- Exception process: Exception is added to the authorization exceptions registry for periodic review \ No newline at end of file diff --git a/docs/adr/98aaa6a5-b1a5-4074-a5ba-5538ff2f5170-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md b/docs/adr/98aaa6a5-b1a5-4074-a5ba-5538ff2f5170-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md new file mode 100644 index 000000000000..e9c89591ddf3 --- /dev/null +++ b/docs/adr/98aaa6a5-b1a5-4074-a5ba-5538ff2f5170-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Handlers + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. MUST: Test authentication handlers MUST extend AuthenticationHandler and override HandleAuthenticateAsync() + +## Policy Block + +- MUST Test authentication handlers MUST extend AuthenticationHandler and override HandleAuthenticateAsync() + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/992104d8-afad-416b-b1a2-d79762911a30-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-attributes-use.md b/docs/adr/992104d8-afad-416b-b1a2-d79762911a30-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-attributes-use.md new file mode 100644 index 000000000000..f026933e1277 --- /dev/null +++ b/docs/adr/992104d8-afad-416b-b1a2-d79762911a30-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-authorization-attributes-use.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Authorization Attributes Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. SHOULD: Authorization attributes SHOULD use typed requirement classes (e.g., ManageUsersRequirement) that implement IAuthorizationRequirement to enable testable and reusable authorization policies + +## Policy Block + +- SHOULD Authorization attributes SHOULD use typed requirement classes (e.g., ManageUsersRequirement) that implement IAuthorizationRequirement to enable testable and reusable authorization policies + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/9af66387-57a0-4867-861d-db50c047a087-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-attributes-placed.md b/docs/adr/9af66387-57a0-4867-861d-db50c047a087-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-attributes-placed.md new file mode 100644 index 000000000000..9dc0b4a965bc --- /dev/null +++ b/docs/adr/9af66387-57a0-4867-861d-db50c047a087-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-attributes-placed.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Authorization Attributes Placed + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. MUST: Authorization attributes MUST be placed on individual HTTP verb methods (HttpGet, HttpPost, HttpPut, HttpDelete) rather than at the controller class level when requirements vary by endpoint + +## Policy Block + +- MUST Authorization attributes MUST be placed on individual HTTP verb methods (HttpGet, HttpPost, HttpPut, HttpDelete) rather than at the controller class level when requirements vary by endpoint + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/9b4c7f7c-92f0-4916-9cd1-03d66a263b7e-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-adminconsole-controller-endpoints.md b/docs/adr/9b4c7f7c-92f0-4916-9cd1-03d66a263b7e-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-adminconsole-controller-endpoints.md new file mode 100644 index 000000000000..012e225ad455 --- /dev/null +++ b/docs/adr/9b4c7f7c-92f0-4916-9cd1-03d66a263b7e-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-adminconsole-controller-endpoints.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Adminconsole Controller Endpoints + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. MUST: All AdminConsole API controller endpoints that require authorization MUST use the generic Authorize attribute with a typed requirement class + +## Policy Block + +- MUST All AdminConsole API controller endpoints that require authorization MUST use the generic Authorize attribute with a typed requirement class + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/9d841473-59fe-4b92-a6a2-5a70f8f090b4-register-core-infrastructure-services-via-dependency-injection-container-infrastructure-services-registered.md b/docs/adr/9d841473-59fe-4b92-a6a2-5a70f8f090b4-register-core-infrastructure-services-via-dependency-injection-container-infrastructure-services-registered.md new file mode 100644 index 000000000000..54626a079e85 --- /dev/null +++ b/docs/adr/9d841473-59fe-4b92-a6a2-5a70f8f090b4-register-core-infrastructure-services-via-dependency-injection-container-infrastructure-services-registered.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Infrastructure Services Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. MUST: Infrastructure services MUST be registered in the dependency injection container using AddSingleton, AddScoped, or AddTransient based on lifecycle requirements + +## Policy Block + +- MUST Infrastructure services MUST be registered in the dependency injection container using AddSingleton, AddScoped, or AddTransient based on lifecycle requirements + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/9daa4246-124f-4135-8383-599b5cb24aba-use-system-text-json-for-scim-api-data-access-serialization-test-authentication-handlers.md b/docs/adr/9daa4246-124f-4135-8383-599b5cb24aba-use-system-text-json-for-scim-api-data-access-serialization-test-authentication-handlers.md new file mode 100644 index 000000000000..4b40df570ff8 --- /dev/null +++ b/docs/adr/9daa4246-124f-4135-8383-599b5cb24aba-use-system-text-json-for-scim-api-data-access-serialization-test-authentication-handlers.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Test Authentication Handlers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. SHOULD: Test authentication handlers SHOULD use System.Security.Claims for constructing test user identities + +## Policy Block + +- SHOULD Test authentication handlers SHOULD use System.Security.Claims for constructing test user identities + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/9dfa9d4e-39bb-4768-b815-2b42f885a25f-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-methods-that.md b/docs/adr/9dfa9d4e-39bb-4768-b815-2b42f885a25f-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-methods-that.md new file mode 100644 index 000000000000..7349165df945 --- /dev/null +++ b/docs/adr/9dfa9d4e-39bb-4768-b815-2b42f885a25f-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-test-methods-that.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Test Methods That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. MUST: Test methods that invoke asynchronous system-under-test methods MUST be declared as async and use await when calling methods returning Task or Task + +## Policy Block + +- MUST Test methods that invoke asynchronous system-under-test methods MUST be declared as async and use await when calling methods returning Task or Task + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/9e21df4f-bead-4cac-b324-68e089a7ab17-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-each-fake-rsa.md b/docs/adr/9e21df4f-bead-4cac-b324-68e089a7ab17-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-each-fake-rsa.md new file mode 100644 index 000000000000..53683580e87c --- /dev/null +++ b/docs/adr/9e21df4f-bead-4cac-b324-68e089a7ab17-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-each-fake-rsa.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Each Fake Rsa + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. SHOULD: Each _FAKE_RSA_KEY_* constant SHOULD be accompanied by inline documentation explaining its intended test scenario (e.g., key rotation, multi-signature validation). + +## Policy Block + +- SHOULD Each _FAKE_RSA_KEY_* constant SHOULD be accompanied by inline documentation explaining its intended test scenario (e.g., key rotation, multi-signature validation). + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/9e7ca0aa-4dab-4df2-bc68-8b163f841d29-register-core-infrastructure-services-via-dependency-injection-container-test-authentication-handlers.md b/docs/adr/9e7ca0aa-4dab-4df2-bc68-8b163f841d29-register-core-infrastructure-services-via-dependency-injection-container-test-authentication-handlers.md new file mode 100644 index 000000000000..2a60c322d609 --- /dev/null +++ b/docs/adr/9e7ca0aa-4dab-4df2-bc68-8b163f841d29-register-core-infrastructure-services-via-dependency-injection-container-test-authentication-handlers.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Test Authentication Handlers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. MAY: Test authentication handlers MAY use hardcoded claims and identities to simulate authenticated users with specific permissions + +## Policy Block + +- MAY Test authentication handlers MAY use hardcoded claims and identities to simulate authenticated users with specific permissions + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/9f5d3eea-eccf-4e82-aef9-dbc13844e4ae-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-tests-append-custom.md b/docs/adr/9f5d3eea-eccf-4e82-aef9-dbc13844e4ae-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-tests-append-custom.md new file mode 100644 index 000000000000..2928063862ac --- /dev/null +++ b/docs/adr/9f5d3eea-eccf-4e82-aef9-dbc13844e4ae-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-tests-append-custom.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Tests Append Custom + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. MAY: Tests MAY append custom headers (e.g., UserAgent) to HTTP requests to simulate specific client behaviors + +## Policy Block + +- MAY Tests MAY append custom headers (e.g., UserAgent) to HTTP requests to simulate specific client behaviors + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/a0860e4d-6381-47ea-b146-63016a984641-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-suites-requiring.md b/docs/adr/a0860e4d-6381-47ea-b146-63016a984641-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-suites-requiring.md new file mode 100644 index 000000000000..42c4b7aea7ff --- /dev/null +++ b/docs/adr/a0860e4d-6381-47ea-b146-63016a984641-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-test-suites-requiring.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Test Suites Requiring + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. SHOULD: Test suites requiring multiple key pairs for protocol validation SHOULD provide at least 5 distinct fake RSA keys to support key rotation, multi-party, and edge case scenarios + +## Policy Block + +- SHOULD Test suites requiring multiple key pairs for protocol validation SHOULD provide at least 5 distinct fake RSA keys to support key rotation, multi-party, and edge case scenarios + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/a09e8e4e-72c4-4cdf-9532-4356d0da43a2-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-production-authorization-policies.md b/docs/adr/a09e8e4e-72c4-4cdf-9532-4356d0da43a2-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-production-authorization-policies.md new file mode 100644 index 000000000000..f6b0865088ee --- /dev/null +++ b/docs/adr/a09e8e4e-72c4-4cdf-9532-4356d0da43a2-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-production-authorization-policies.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Production Authorization Policies + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MUST: Production authorization policies MUST call policy.RequireAuthenticatedUser() to enforce authentication as a prerequisite + +## Policy Block + +- MUST Production authorization policies MUST call policy.RequireAuthenticatedUser() to enforce authentication as a prerequisite + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/a1e870a0-0dc1-4fe8-a9cf-2fac8e888b6e-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-test-environments-configure.md b/docs/adr/a1e870a0-0dc1-4fe8-a9cf-2fac8e888b6e-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-test-environments-configure.md new file mode 100644 index 000000000000..309d352e8ab8 --- /dev/null +++ b/docs/adr/a1e870a0-0dc1-4fe8-a9cf-2fac8e888b6e-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-test-environments-configure.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Test Environments Configure + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. SHOULD: Test environments SHOULD configure authorization policies with RequireAssertion to enable controlled test scenarios + +## Policy Block + +- SHOULD Test environments SHOULD configure authorization policies with RequireAssertion to enable controlled test scenarios + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/a358d52b-a70b-42c1-b2aa-03d2f8fae6e1-establish-http-client-boundaries-for-external-service-integration-http-request-headers.md b/docs/adr/a358d52b-a70b-42c1-b2aa-03d2f8fae6e1-establish-http-client-boundaries-for-external-service-integration-http-request-headers.md new file mode 100644 index 000000000000..866878f53739 --- /dev/null +++ b/docs/adr/a358d52b-a70b-42c1-b2aa-03d2f8fae6e1-establish-http-client-boundaries-for-external-service-integration-http-request-headers.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: Http Request Headers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. SHOULD: HTTP request headers (e.g., UserAgent, Accept) SHOULD be explicitly configured when external services require specific header values for routing or identification + +## Policy Block + +- SHOULD HTTP request headers (e.g., UserAgent, Accept) SHOULD be explicitly configured when external services require specific header values for routing or identification + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/a3851f8b-cb87-4a32-b0f2-afcdd5864124-register-core-infrastructure-services-via-dependency-injection-container-test-environments-register.md b/docs/adr/a3851f8b-cb87-4a32-b0f2-afcdd5864124-register-core-infrastructure-services-via-dependency-injection-container-test-environments-register.md new file mode 100644 index 000000000000..7a3b067bbb19 --- /dev/null +++ b/docs/adr/a3851f8b-cb87-4a32-b0f2-afcdd5864124-register-core-infrastructure-services-via-dependency-injection-container-test-environments-register.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Test Environments Register + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. MUST: Test environments MUST register no-op or mock implementations for external service dependencies (e.g., IMailService) to prevent side effects + +## Policy Block + +- MUST Test environments MUST register no-op or mock implementations for external service dependencies (e.g., IMailService) to prevent side effects + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/a3f292d1-1cab-4f76-991e-4a83fba87e42-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-failures-authorizeasync.md b/docs/adr/a3f292d1-1cab-4f76-991e-4a83fba87e42-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-failures-authorizeasync.md new file mode 100644 index 000000000000..f23f4a04f2e2 --- /dev/null +++ b/docs/adr/a3f292d1-1cab-4f76-991e-4a83fba87e42-enforce-authorization-service-integration-at-controller-layer-for-organization-user-operations-authorization-failures-authorizeasync.md @@ -0,0 +1,122 @@ +# Enforce Authorization Service Integration at Controller Layer for Organization User Operations: Authorization Failures Authorizeasync + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers managing organization user operations and collection access within the AdminConsole namespace. + +## Context + +- The OrganizationUsersController manages sensitive operations including user invitations, confirmations, role assignments, and collection access modifications within multi-tenant organizations +- Authorization decisions require evaluating multiple factors including user roles, collection permissions, organization policies, and self-modification constraints that cannot be expressed through simple attribute-based authorization alone +- The controller coordinates between 30+ injected dependencies including repositories, commands, queries, and the IAuthorizationService to enforce fine-grained access control +- Operations like ModifyUserAccess on collections require runtime authorization checks against specific resource instances rather than static role-based rules +- The codebase uses Microsoft.AspNetCore.Authorization framework with custom requirements (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) applied via Authorize attributes and programmatic AuthorizeAsync calls + +## Problem Statement + +Controllers handling organization user management must enforce authorization at multiple granularities—endpoint-level role requirements, operation-specific permissions, and resource-instance access control—while preventing privilege escalation scenarios such as self-assignment to restricted collections or unauthorized modification of user permissions. Without consistent integration of IAuthorizationService for runtime authorization checks, controllers risk exposing authorization gaps where attribute-based authorization alone is insufficient. + +## Decision + +1. MUST: Authorization failures from AuthorizeAsync MUST throw NotFoundException rather than UnauthorizedException to prevent enumeration attacks + +## Policy Block + +- MUST Authorization failures from AuthorizeAsync MUST throw NotFoundException rather than UnauthorizedException to prevent enumeration attacks + +In scope: +- All controllers in Bit.Api.AdminConsole.Controllers namespace +- Endpoints managing OrganizationUser entities including invite, confirm, update, revoke, restore, and delete operations +- Operations modifying user-collection associations or group memberships +- Account recovery and reset password enrollment endpoints + +Out of scope: +- Public unauthenticated endpoints +- Read-only query endpoints that do not expose sensitive cryptographic material +- Internal service-to-service calls within the same trust boundary +- Background jobs or scheduled tasks not initiated by user requests + +Exceptions: +- EXC-001: Endpoints returning only mini-details (Id, Email, Name) for collection management UI may use simplified MemberOrProviderRequirement without resource-level checks + +## Rationale + +- The evidence shows IAuthorizationService injected and used for runtime authorization checks against collection resources, demonstrating that attribute-based authorization alone is insufficient for the required access control granularity +- Multiple authorization namespaces (Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Collections, Bit.Api.AdminConsole.Authorization.Requirements) indicate a structured authorization layer separate from business logic +- The pattern of throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing enumeration risk +- Self-modification checks against organizationAbility.AllowAdminAccessToAllCollectionItems prevent privilege escalation where admins could grant themselves access to restricted collections + +## Consequences + +Positive: +- Fine-grained authorization at the resource instance level prevents unauthorized access to specific collections even when users have organization-level permissions +- Separation of authorization logic into dedicated requirements and handlers improves testability and reusability across controllers +- Consistent NotFoundException responses on authorization failures reduce information leakage and enumeration attack surface +- Layered authorization (attribute-based + programmatic) provides defense in depth against authorization bypass vulnerabilities + +Negative: +- Increased controller complexity with 30+ constructor dependencies and multiple authorization check points throughout action methods +- Performance overhead from multiple database queries to fetch collections for authorization checks before operations +- Risk of authorization bypass if developers forget to add programmatic AuthorizeAsync calls for new endpoints or operations +- Debugging authorization failures requires tracing through multiple layers of requirements, handlers, and policy evaluations + +## Alternatives + +- Use only attribute-based authorization with custom requirements at the method level without programmatic AuthorizeAsync calls (rejected) + Rejected because: Attribute-based authorization cannot access runtime resource instances (specific collections) needed for ModifyUserAccess checks, leading to coarse-grained authorization insufficient for multi-tenant collection permissions + When valid: Simple role-based access control where all users with a role have identical permissions to all resources +- Implement authorization logic directly in controller methods using repository queries and conditional checks (rejected) + Rejected because: Duplicates authorization logic across controllers, reduces testability, and makes it difficult to audit or update authorization rules consistently across the application + When valid: Prototypes or single-controller applications where reusability is not a concern +- Move all authorization checks into command/query handlers to keep controllers thin (deferred) + Rejected because: Would require refactoring 30+ command/query interfaces and implementations; current pattern works but could be improved in future architectural iteration + When valid: Greenfield projects or major refactoring efforts where clean architecture boundaries are prioritized + +## Risks + +- Developers may forget to add AuthorizeAsync checks for new endpoints, creating authorization gaps + Mitigation: Implement automated security testing that verifies all endpoints modifying collections call AuthorizeAsync; add code review checklist items for authorization verification + Owner: Security team and API development team +- Performance degradation from multiple authorization queries per request, especially for bulk operations + Mitigation: Implement caching for organization abilities and user permissions; batch authorization checks where possible; monitor authorization query performance in production + Owner: Performance engineering team +- Inconsistent exception handling (NotFoundException vs UnauthorizedException) may leak information if not applied uniformly + Mitigation: Create shared authorization helper methods that enforce consistent exception patterns; document the security rationale in code comments + Owner: Engineering team + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors alongside other dependencies; store as private readonly field +- For collection modification endpoints, fetch collection entities via ICollectionRepository.GetManyByManyIdsAsync before calling AuthorizeAsync with BulkCollectionOperations.ModifyUserAccess +- When authorization fails (Succeeded == false), throw NotFoundException() without additional details to prevent enumeration +- For self-modification scenarios, retrieve organizationAbility via IOrganizationAbilityCacheService and check AllowAdminAccessToAllCollectionItems before allowing collection/group additions +- Separate editable collections from read-only collections by checking authorization on each collection and preserving read-only ones during updates + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ | grep -c 'private readonly' +- grep -r 'AuthorizeAsync.*BulkCollectionOperations.ModifyUserAccess' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A 5 'AuthorizeAsync' + +Accept when: +- All controllers in Bit.Api.AdminConsole.Controllers managing organization users inject IAuthorizationService +- All endpoints modifying collection access call AuthorizeAsync with appropriate requirements before persistence +- Authorization failures consistently throw NotFoundException to prevent enumeration + +## Enforcement + +- Verified by: Automated security tests verifying AuthorizeAsync calls on protected endpoints +- Verified by: Code review checklist requiring authorization verification for new endpoints +- Verified by: Static analysis rules detecting IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if security tests detect missing authorization checks +- Violation handling: Pull requests blocked until code review confirms authorization implementation +- Violation handling: Security team notified of authorization-related test failures for investigation +- Exception process: Document exception rationale in ADR exception log with security team approval +- Exception process: Add compensating controls such as additional logging or monitoring +- Exception process: Schedule technical debt ticket for future remediation if temporary exception granted \ No newline at end of file diff --git a/docs/adr/a4882536-e976-4b5b-b9c4-76184baf709d-adopt-http-client-abstraction-for-external-service-integration-external-service-clients.md b/docs/adr/a4882536-e976-4b5b-b9c4-76184baf709d-adopt-http-client-abstraction-for-external-service-integration-external-service-clients.md new file mode 100644 index 000000000000..b062a6f56d79 --- /dev/null +++ b/docs/adr/a4882536-e976-4b5b-b9c4-76184baf709d-adopt-http-client-abstraction-for-external-service-integration-external-service-clients.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: External Service Clients + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. SHOULD: External service clients SHOULD implement rate limiting when integrating with third-party APIs to prevent quota exhaustion + +## Policy Block + +- SHOULD External service clients SHOULD implement rate limiting when integrating with third-party APIs to prevent quota exhaustion + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/a5bdfb20-cb01-4912-b128-8694d29c60b6-enforce-authorization-attributes-on-api-controllers-via-unit-tests-http-action-methods.md b/docs/adr/a5bdfb20-cb01-4912-b128-8694d29c60b6-enforce-authorization-attributes-on-api-controllers-via-unit-tests-http-action-methods.md new file mode 100644 index 000000000000..edae60259ffc --- /dev/null +++ b/docs/adr/a5bdfb20-cb01-4912-b128-8694d29c60b6-enforce-authorization-attributes-on-api-controllers-via-unit-tests-http-action-methods.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Http Action Methods + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. MUST: All HTTP action methods (decorated with HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST have method-level authorization attributes + +## Policy Block + +- MUST All HTTP action methods (decorated with HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) MUST have method-level authorization attributes + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/a82901b9-0179-442c-841a-6b741dd1b9f5-register-core-infrastructure-services-via-dependency-injection-container-authentication-schemes-registered.md b/docs/adr/a82901b9-0179-442c-841a-6b741dd1b9f5-register-core-infrastructure-services-via-dependency-injection-container-authentication-schemes-registered.md new file mode 100644 index 000000000000..b45a95db16ba --- /dev/null +++ b/docs/adr/a82901b9-0179-442c-841a-6b741dd1b9f5-register-core-infrastructure-services-via-dependency-injection-container-authentication-schemes-registered.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Authentication Schemes Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. MUST: Authentication schemes MUST be registered via AddAuthentication with explicit scheme names before configuring authorization policies + +## Policy Block + +- MUST Authentication schemes MUST be registered via AddAuthentication with explicit scheme names before configuring authorization policies + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/aa269035-dd58-4901-be93-7ced95cd3b0c-enforce-authorization-service-pattern-for-access-control-decisions-controllers-inject-iauthorizationservice.md b/docs/adr/aa269035-dd58-4901-be93-7ced95cd3b0c-enforce-authorization-service-pattern-for-access-control-decisions-controllers-inject-iauthorizationservice.md new file mode 100644 index 000000000000..b05722615103 --- /dev/null +++ b/docs/adr/aa269035-dd58-4901-be93-7ced95cd3b0c-enforce-authorization-service-pattern-for-access-control-decisions-controllers-inject-iauthorizationservice.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Controllers Inject Iauthorizationservice + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MUST: Controllers MUST inject IAuthorizationService as a constructor dependency and store it as a private readonly field + +## Policy Block + +- MUST Controllers MUST inject IAuthorizationService as a constructor dependency and store it as a private readonly field + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/aaaf4b07-0f57-4370-94a8-edfd8a440f2c-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-extended-cache-utilities.md b/docs/adr/aaaf4b07-0f57-4370-94a8-edfd8a440f2c-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-extended-cache-utilities.md new file mode 100644 index 000000000000..2dcdf8eae317 --- /dev/null +++ b/docs/adr/aaaf4b07-0f57-4370-94a8-edfd8a440f2c-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-extended-cache-utilities.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Extended Cache Utilities + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. MAY: Extended cache utilities MAY provide additional configuration options beyond standard IDistributedCache for Redis-specific features + +## Policy Block + +- MAY Extended cache utilities MAY provide additional configuration options beyond standard IDistributedCache for Redis-specific features + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/aab5279c-67a4-460e-827a-dedceac4a97e-register-core-infrastructure-services-via-dependency-injection-container-service-registration-occur.md b/docs/adr/aab5279c-67a4-460e-827a-dedceac4a97e-register-core-infrastructure-services-via-dependency-injection-container-service-registration-occur.md new file mode 100644 index 000000000000..81c0799fc976 --- /dev/null +++ b/docs/adr/aab5279c-67a4-460e-827a-dedceac4a97e-register-core-infrastructure-services-via-dependency-injection-container-service-registration-occur.md @@ -0,0 +1,103 @@ +# Register Core Infrastructure Services via Dependency Injection Container: Service Registration Occur + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.AspNetCore.Authentication framework with custom test authentication handlers for integration testing scenarios +- Service registration patterns appear in ScimApplicationFactory.cs, which configures authentication schemes, authorization policies, and infrastructure services including IMailService implementations +- The application requires boundary definitions between external SCIM clients (Okta) and internal service implementations, necessitating explicit service registration +- Integration tests require isolated service configurations with test doubles (NoopMailService) to avoid external dependencies during test execution +- The authentication and authorization pipeline uses claims-based identity with organization-scoped permissions enforced through policy assertions + +## Problem Statement + +Integration test environments require explicit service boundary definitions and dependency injection configuration to isolate external dependencies, configure test authentication handlers, and ensure consistent service resolution across test scenarios without coupling to production infrastructure. + +## Decision + +1. SHOULD: Service registration SHOULD occur in factory or startup classes that configure the application host for specific environments + +## Policy Block + +- SHOULD Service registration SHOULD occur in factory or startup classes that configure the application host for specific environments + +## Rationale + +- The evidence shows explicit service registration patterns (AddSingleton) in ScimApplicationFactory.cs, demonstrating intentional boundary definition through dependency injection +- Test authentication handlers (TestAuthHandler) extend AuthenticationHandler and are registered via AddAuthentication, establishing a clear pattern for test environment configuration +- The authorization configuration uses AddAuthorization with policy-based assertions (RequireAssertion(a => true)), indicating explicit boundary enforcement at the authorization layer +- The pattern enables isolation of external dependencies during integration testing while maintaining consistent service resolution patterns across environments + +## Consequences + +Positive: +- Service boundaries are explicitly defined through interface registrations, improving testability and enabling dependency substitution +- Integration tests can execute without external dependencies by registering no-op implementations, reducing test fragility and execution time +- Authentication and authorization configuration is centralized in factory classes, providing clear visibility into security boundary definitions +- The dependency injection pattern enables consistent service resolution across controllers, handlers, and middleware components + +Negative: +- Service registration configuration must be maintained separately for each environment (test, production), increasing configuration complexity +- Incorrect service lifetime registration (singleton vs scoped) can introduce subtle bugs related to state management and concurrency +- Test-specific service implementations (NoopMailService) require ongoing maintenance to match production interface contracts +- Authorization policies using RequireAssertion with lambda expressions are not statically analyzable, making policy validation more difficult + +## Alternatives + +- Use service locator pattern with manual instantiation instead of dependency injection container (rejected) + Rejected because: Service locator pattern hides dependencies, makes testing more difficult, and couples components to the locator infrastructure rather than explicit interfaces + When valid: May be appropriate for legacy codebases with extensive static dependencies that cannot be easily refactored +- Use concrete class instantiation in tests without interface abstractions (rejected) + Rejected because: Direct instantiation couples tests to production implementations, preventing isolation of external dependencies and making tests fragile to infrastructure changes + When valid: Acceptable for pure domain logic classes with no external dependencies or side effects +- Use attribute-based service registration with automatic discovery (deferred) + Rejected because: Not rejected; deferred pending evaluation of convention-based registration benefits versus explicit registration clarity + When valid: Useful in large codebases with many services following consistent registration patterns where convention reduces boilerplate + +## Risks + +- Service lifetime mismatches (e.g., singleton service depending on scoped service) can cause runtime errors or state corruption + Mitigation: Implement service lifetime validation in CI pipeline and use ASP.NET Core's ValidateScopes option in development environments + Owner: engineering team +- Test service implementations may diverge from production implementations, causing tests to pass while production fails + Mitigation: Maintain integration tests that use production service implementations against test infrastructure, and enforce interface contract tests + Owner: engineering team +- Authorization policies using RequireAssertion with complex lambda expressions are difficult to test and validate comprehensively + Mitigation: Extract authorization logic into testable policy handlers implementing IAuthorizationHandler, and add unit tests for authorization logic + Owner: engineering team + +## Implementation Notes + +- Register services in ConfigureServices or equivalent factory methods using the IServiceCollection extension methods (AddSingleton, AddScoped, AddTransient) +- For test environments, create factory classes (e.g., ScimApplicationFactory) that override service registrations with test doubles +- Use interface abstractions (IMailService) for all external dependencies to enable substitution in test environments +- Configure authentication schemes before authorization policies, as policies may depend on authentication scheme configuration +- Consider extracting complex authorization logic from RequireAssertion lambdas into dedicated IAuthorizationHandler implementations for better testability + +## Continuation Context + + +Verify commands: +- grep -r 'AddSingleton\|AddScoped\|AddTransient' --include='*.cs' | grep -v '.Test' | wc -l +- grep -r 'AddAuthentication' --include='*.cs' | head -5 +- find . -name '*Factory.cs' -path '*/Test/*' -exec grep -l 'IServiceCollection' {} \; + +Accept when: +- Service registration commands return non-zero counts indicating active use of dependency injection patterns +- Authentication configuration is present in application startup or factory classes +- Test factory classes exist that configure service registrations for test environments + +## Enforcement + +- Verified by: Code review verification that new services are registered via dependency injection rather than direct instantiation +- Verified by: Static analysis tools checking for service locator anti-patterns and unregistered dependency usage +- Verified by: Integration test execution confirming service resolution succeeds for all registered interfaces +- Violation handling: Build failures when services cannot be resolved from the dependency injection container at application startup +- Violation handling: Code review feedback requiring refactoring of direct instantiation to use dependency injection +- Violation handling: Runtime exceptions (InvalidOperationException) when attempting to resolve unregistered services +- Exception process: Document justification for direct instantiation in code comments when dependency injection is not feasible +- Exception process: Obtain architecture review approval for service locator pattern usage in legacy integration scenarios +- Exception process: Create technical debt tickets for components that cannot immediately adopt dependency injection patterns \ No newline at end of file diff --git a/docs/adr/aaf34ea5-54c3-43cc-a210-03bf483dedb2-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-management-modules.md b/docs/adr/aaf34ea5-54c3-43cc-a210-03bf483dedb2-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-management-modules.md new file mode 100644 index 000000000000..27fd35560b51 --- /dev/null +++ b/docs/adr/aaf34ea5-54c3-43cc-a210-03bf483dedb2-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-management-modules.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Key Management Modules + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. MAY: Key management modules MAY use std::collections::HashSet for tracking key identifiers or managing key lifecycle state + +## Policy Block + +- MAY Key management modules MAY use std::collections::HashSet for tracking key identifiers or managing key lifecycle state + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/ab20330d-42a3-40d9-954b-b5fb1aaeff15-adopt-http-client-abstraction-for-external-service-integration-cross-language-ffi.md b/docs/adr/ab20330d-42a3-40d9-954b-b5fb1aaeff15-adopt-http-client-abstraction-for-external-service-integration-cross-language-ffi.md new file mode 100644 index 000000000000..fa3958a18600 --- /dev/null +++ b/docs/adr/ab20330d-42a3-40d9-954b-b5fb1aaeff15-adopt-http-client-abstraction-for-external-service-integration-cross-language-ffi.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Cross Language Ffi + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. MUST: Cross-language FFI boundaries involving external HTTP communication MUST use safe string marshaling patterns (CStr, CString) with proper memory management + +## Policy Block + +- MUST Cross-language FFI boundaries involving external HTTP communication MUST use safe string marshaling patterns (CStr, CString) with proper memory management + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/abc628f2-d591-45bf-8221-4b8a79fe0b5a-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-framework-dbcontext.md b/docs/adr/abc628f2-d591-45bf-8221-4b8a79fe0b5a-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-framework-dbcontext.md new file mode 100644 index 000000000000..e6ff42c40edf --- /dev/null +++ b/docs/adr/abc628f2-d591-45bf-8221-4b8a79fe0b5a-adopt-dbset-based-entity-collection-modeling-in-entity-framework-contexts-entity-framework-dbcontext.md @@ -0,0 +1,113 @@ +# Adopt DbSet-Based Entity Collection Modeling in Entity Framework Contexts: Entity Framework Dbcontext + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Entity Framework as the ORM layer for database access, requiring a centralized context to manage entity collections and database operations +- DatabaseContext.cs exposes 50+ domain entities as DbSet properties, establishing a single point of access for all database operations across AccessPolicy, Cipher, Collection, Organization, User, and other core domain models +- The Rust SDK (lib.rs) demonstrates a parallel pattern using structured data types (cipher, rsa_keys) with std::ffi bindings for cross-language interoperability, indicating multi-language data modeling requirements +- Both implementations use explicit type declarations for data structures rather than dynamic or schema-less approaches, prioritizing compile-time type safety and IDE tooling support + +## Problem Statement + +Without a consistent approach to modeling entity collections in ORM contexts, teams may adopt inconsistent patterns for exposing database entities, leading to fragmented data access patterns, reduced discoverability of available entities, and increased cognitive load when navigating the data layer. The codebase requires a standardized method for declaring and organizing entity collections that supports both type safety and maintainability across multiple technology stacks. + +## Decision + +1. MUST: Entity Framework DbContext implementations MUST expose each persistent entity type as a public DbSet property with explicit getter and setter + +## Policy Block + +- MUST Entity Framework DbContext implementations MUST expose each persistent entity type as a public DbSet property with explicit getter and setter + +In scope: +- All Entity Framework DbContext implementations in the Infrastructure.EntityFramework namespace +- Primary DatabaseContext class managing application-wide entity collections +- Cross-language data structure definitions requiring FFI bindings (Rust SDK) +- Entity types representing persistent domain models (User, Organization, Cipher, Collection, etc.) + +Out of scope: +- View models or DTOs used only for API responses without database persistence +- Temporary or in-memory data structures not requiring ORM mapping +- Third-party library contexts or external database connections +- Read-only query result types without corresponding database tables + +## Rationale + +- The DatabaseContext.cs evidence shows 50+ DbSet properties following a consistent pattern, demonstrating an established architectural decision to centralize entity collection management in a single context class +- Explicit DbSet declarations provide compile-time type safety, enabling IDE autocomplete, refactoring support, and early detection of entity access errors +- The parallel pattern in Rust SDK (lib.rs) using std::ffi types and explicit struct definitions indicates a broader architectural principle of preferring strongly-typed data modeling across language boundaries +- Centralizing entity collections in DbContext improves discoverability and reduces the risk of teams creating ad-hoc data access patterns outside the established ORM layer + +## Consequences + +Positive: +- Single source of truth for all persistent entity types, improving code discoverability and reducing duplication +- Strong compile-time type checking prevents runtime errors from incorrect entity access patterns +- IDE tooling provides autocomplete and navigation support for all registered entity collections +- Consistent naming conventions (plural DbSet properties) reduce cognitive load when working across different entity types + +Negative: +- DatabaseContext class grows large with 50+ properties, potentially becoming a maintenance bottleneck and violating single responsibility principle +- Adding new entities requires modifying the central context class, creating merge conflicts in high-velocity teams +- All entities are loaded into the context metadata model even if only a subset is used in specific application scenarios, increasing startup time +- Tight coupling between the context class and all entity types makes it difficult to modularize or split the data layer + +## Alternatives + +- Use multiple bounded DbContext classes, each managing a subset of related entities (e.g., IdentityContext, VaultContext, AdminContext) (rejected) + Rejected because: Evidence shows a single DatabaseContext with all entities, indicating a preference for centralized management despite the large surface area. Splitting would require significant refactoring and coordination across repository patterns. + When valid: Valid for greenfield projects or when clear bounded contexts exist with minimal cross-context queries +- Use dynamic entity registration via reflection or configuration files rather than explicit DbSet properties (rejected) + Rejected because: Loses compile-time type safety and IDE support. Evidence shows explicit DbSet declarations throughout DatabaseContext.cs, prioritizing developer experience and early error detection. + When valid: Valid for plugin architectures where entity types are unknown at compile time +- Use repository pattern with generic IRepository interfaces, hiding DbSet details behind abstraction (deferred) + Rejected because: Not rejected; evidence shows DbSet exposure but does not preclude repository layer on top. May be implemented as complementary pattern. + When valid: Valid as an additional abstraction layer for complex query logic or multi-database scenarios + +## Risks + +- DatabaseContext class becomes a megaclass with 100+ properties as the application grows, violating maintainability principles and causing frequent merge conflicts + Mitigation: Establish entity count thresholds (e.g., 75 entities) that trigger context splitting discussions. Use partial classes or IEntityTypeConfiguration to distribute configuration logic. + Owner: Data Access Team +- Cross-language data modeling patterns (C# DbSet vs Rust structs) diverge over time, creating inconsistent data access semantics between SDK implementations + Mitigation: Document shared data modeling principles in architecture guidelines. Implement automated schema validation tests that verify consistency across language boundaries. + Owner: Platform Architecture Team +- Entity Framework context initialization time increases as entity count grows, impacting application startup performance + Mitigation: Use lazy loading for DbSet properties where appropriate. Monitor context initialization metrics and consider compiled models for production deployments. + Owner: Performance Engineering Team + +## Implementation Notes + +- When adding new entities, declare DbSet properties in DatabaseContext.cs following the established naming pattern (plural nouns) +- Group related DbSet properties together with comments indicating domain boundaries (e.g., // Access Control Entities, // Vault Entities) +- Use IEntityTypeConfiguration classes in the Configurations folder for complex entity mappings rather than inline OnModelCreating logic +- For cross-language scenarios, maintain parallel type definitions with explicit FFI bindings (std::ffi::CString for Rust) and document mapping conventions + +## Continuation Context + + +Verify commands: +- grep -r 'public DbSet<' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs | wc -l +- dotnet build src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj --no-incremental +- grep -E 'DbSet<\w+>\s+\w+s\s+{\s+get;\s+set;\s+}' src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs + +Accept when: +- All persistent entity types are exposed as public DbSet properties in DatabaseContext with plural naming +- The solution compiles without errors, confirming all DbSet declarations are valid and entity types are properly defined +- DbSet property declarations follow the pattern 'public DbSet EntityTypes { get; set; }' with consistent formatting + +## Enforcement + +- Verified by: Code review checklist requiring DbSet registration for all new entity types +- Verified by: Automated build verification ensuring DatabaseContext compiles successfully +- Verified by: Architecture decision record review during sprint planning for new domain models +- Violation handling: Pull requests adding entity types without corresponding DbSet properties are blocked by code review +- Violation handling: Build failures from missing entity registrations halt CI pipeline until resolved +- Violation handling: Quarterly architecture audits identify entities accessed outside the DbContext pattern for remediation +- Exception process: Temporary entities or experimental features may defer DbSet registration with explicit TODO comments and tracking issue +- Exception process: Read-only query result types (keyless entities) document exemption rationale in OnModelCreating configuration +- Exception process: Cross-cutting concerns (audit logs, telemetry) may use alternative persistence mechanisms with architecture team approval \ No newline at end of file diff --git a/docs/adr/aca2792a-f5da-41d3-91ed-f225a11fc94c-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-generation-functions.md b/docs/adr/aca2792a-f5da-41d3-91ed-f225a11fc94c-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-generation-functions.md new file mode 100644 index 000000000000..080314c4ff2e --- /dev/null +++ b/docs/adr/aca2792a-f5da-41d3-91ed-f225a11fc94c-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-key-generation-functions.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Key Generation Functions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. MUST: Key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) MUST expose public contracts (pub) at the FFI boundary with memory management functions (free_c_string) + +## Policy Block + +- MUST Key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) MUST expose public contracts (pub) at the FFI boundary with memory management functions (free_c_string) + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/ace52160-226e-413e-80cd-682f2d78db99-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-fake-cryptographic-key.md b/docs/adr/ace52160-226e-413e-80cd-682f2d78db99-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-fake-cryptographic-key.md new file mode 100644 index 000000000000..d6f6de565662 --- /dev/null +++ b/docs/adr/ace52160-226e-413e-80cd-682f2d78db99-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-fake-cryptographic-key.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Fake Cryptographic Key + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. SHOULD: Fake cryptographic key constants SHOULD be marked with naming conventions that make their test-only nature explicit. + +## Policy Block + +- SHOULD Fake cryptographic key constants SHOULD be marked with naming conventions that make their test-only nature explicit. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/ad5d08c9-8728-47e5-b261-fa5e075ee348-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-linq.md b/docs/adr/ad5d08c9-8728-47e5-b261-fa5e075ee348-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-linq.md new file mode 100644 index 000000000000..e99ef96d3e00 --- /dev/null +++ b/docs/adr/ad5d08c9-8728-47e5-b261-fa5e075ee348-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-linq.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Use Linq + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. MAY: Tests MAY use LINQ Select with ToArray/ToList to construct test data collections for member operations + +## Policy Block + +- MAY Tests MAY use LINQ Select with ToArray/ToList to construct test data collections for member operations + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/af1e829e-bf47-40d9-bc3a-c282b0a91de4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md b/docs/adr/af1e829e-bf47-40d9-bc3a-c282b0a91de4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md new file mode 100644 index 000000000000..497d2d1599aa --- /dev/null +++ b/docs/adr/af1e829e-bf47-40d9-bc3a-c282b0a91de4-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-fake-rsa-keys.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Fake Rsa Keys + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. MUST: Fake RSA keys MUST be declared as const string literals containing complete PEM-encoded PRIVATE KEY blocks in PKCS#8 format + +## Policy Block + +- MUST Fake RSA keys MUST be declared as const string literals containing complete PEM-encoded PRIVATE KEY blocks in PKCS#8 format + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/aff187d4-e8a6-49ef-9f8a-0a6f86b4d48f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-accepting.md b/docs/adr/aff187d4-e8a6-49ef-9f8a-0a6f86b4d48f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-accepting.md new file mode 100644 index 000000000000..4ff62ae0d231 --- /dev/null +++ b/docs/adr/aff187d4-e8a6-49ef-9f8a-0a6f86b4d48f-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-accepting.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Accepting + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. MUST: All FFI functions accepting C string pointers (c_char) MUST validate input using std::ffi::CStr before dereferencing or converting to Rust types + +## Policy Block + +- MUST All FFI functions accepting C string pointers (c_char) MUST validate input using std::ffi::CStr before dereferencing or converting to Rust types + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/b18395c7-d0da-4b8c-8091-bb4e2da35352-enforce-authorization-attributes-on-api-controllers-via-unit-tests-swagger-openapi-document.md b/docs/adr/b18395c7-d0da-4b8c-8091-bb4e2da35352-enforce-authorization-attributes-on-api-controllers-via-unit-tests-swagger-openapi-document.md new file mode 100644 index 000000000000..d2812681381f --- /dev/null +++ b/docs/adr/b18395c7-d0da-4b8c-8091-bb4e2da35352-enforce-authorization-attributes-on-api-controllers-via-unit-tests-swagger-openapi-document.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Swagger Openapi Document + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. SHOULD: Swagger/OpenAPI document filters SHOULD validate that operation IDs are unique to prevent duplicate endpoint definitions + +## Policy Block + +- SHOULD Swagger/OpenAPI document filters SHOULD validate that operation IDs are unique to prevent duplicate endpoint definitions + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/b1e7db38-2432-46ef-944c-12699fc054f2-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-log-operation.md b/docs/adr/b1e7db38-2432-46ef-944c-12699fc054f2-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-log-operation.md new file mode 100644 index 000000000000..c9993a8fac30 --- /dev/null +++ b/docs/adr/b1e7db38-2432-46ef-944c-12699fc054f2-adopt-command-query-separation-with-async-execution-for-service-api-boundaries-controllers-log-operation.md @@ -0,0 +1,102 @@ +# Adopt Command-Query Separation with Async Execution for Service API Boundaries: Controllers Log Operation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Service API controllers in Bit.SeederApi separate command execution (scene creation/destruction) from query operations through dedicated interfaces (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand, IQueries) +- Controllers coordinate asynchronous execution patterns using Task-based async/await for all data access operations, including ExecuteAsync, DestroyAsync, and query methods +- HTTP endpoints expose RESTful boundaries (POST /seed, DELETE /batch, DELETE /{playId}) that map directly to command and query interfaces rather than direct data access +- Error handling distinguishes between aggregate failures (batch operations) and single execution failures (SceneExecutionException), providing structured error responses at the API boundary +- Test infrastructure in ScimApplicationFactory demonstrates similar patterns with async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) coordinating service boundaries and authentication handlers + +## Problem Statement + +Service API boundaries require a consistent pattern for coordinating data access operations that maintains separation between command execution and query operations while providing predictable error handling and asynchronous execution semantics across HTTP endpoints. + +## Decision + +1. SHOULD: Controllers SHOULD log operation context at API boundaries using structured logging with relevant identifiers (PlayIds, Template, OlderThan) + +## Policy Block + +- SHOULD Controllers SHOULD log operation context at API boundaries using structured logging with relevant identifiers (PlayIds, Template, OlderThan) + +## Rationale + +- Evidence from SeedController.cs shows consistent use of injected command/query interfaces (sceneExecutor, destroyBatchScenesCommand, destroySceneCommand) rather than direct data access, establishing clear architectural boundaries +- All observed API methods use async/await patterns (await sceneExecutor.ExecuteAsync, await destroyBatchScenesCommand.DestroyAsync, await destroySceneCommand.DestroyAsync), indicating standardized asynchronous coordination +- HTTP route attributes ([HttpPost], [HttpDelete]) and method signatures (SeedAsync, DeleteBatchAsync, DeleteAsync) demonstrate RESTful boundary definitions that delegate to command/query abstractions +- ScimApplicationFactory test infrastructure validates this pattern across multiple HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) with consistent async coordination and authentication handling + +## Consequences + +Positive: +- Clear separation between API boundary concerns and data access logic enables independent evolution of HTTP contracts and persistence implementations +- Asynchronous execution patterns prevent thread blocking at service boundaries, improving scalability and resource utilization under concurrent load +- Command-query interface abstractions facilitate testing through dependency injection and mocking without requiring actual data access infrastructure +- Structured error handling at API boundaries provides consistent client experience and enables centralized logging of operation failures + +Negative: +- Additional abstraction layers (interfaces, command/query objects) increase code volume and navigation complexity compared to direct data access from controllers +- Async/await patterns introduce complexity in error handling and debugging, particularly with aggregate exceptions and nested async operations +- Interface proliferation (ISceneExecutor, IDestroySceneCommand, IDestroyBatchScenesCommand) may lead to maintenance overhead when operation signatures evolve +- Coordination overhead from async task scheduling may impact latency for simple, low-latency operations that could execute synchronously + +## Alternatives + +- Direct data access from controllers using synchronous Entity Framework DbContext operations (rejected) + Rejected because: Synchronous data access blocks threads at API boundaries, reducing scalability and preventing efficient handling of I/O-bound operations. Evidence shows consistent async patterns across all observed endpoints. + When valid: Only appropriate for non-production prototypes or internal tools with guaranteed single-user access and no scalability requirements +- Repository pattern with generic CRUD operations instead of command-query separation (rejected) + Rejected because: Generic repository patterns do not capture domain-specific operations like ExecuteAsync(template, arguments) or DestroyAsync(playId), losing semantic clarity at the API boundary. Evidence shows specialized command interfaces. + When valid: Suitable for simple CRUD-only services with no complex business operations or workflow orchestration +- Mediator pattern (e.g., MediatR) for decoupling controllers from command/query handlers (deferred) + Rejected because: Not rejected; evidence does not show mediator usage but pattern could complement existing command-query separation by adding request/response pipeline capabilities + When valid: When cross-cutting concerns (validation, logging, transaction management) need to be applied uniformly across all command/query operations + +## Risks + +- Interface proliferation leads to maintenance burden when operation signatures change, requiring updates across multiple layers (controller, interface, implementation) + Mitigation: Establish naming conventions and code generation templates for command/query interfaces. Use integration tests to detect signature mismatches early. + Owner: engineering team +- Async execution patterns may mask performance issues or deadlocks, particularly when mixing async and synchronous code paths + Mitigation: Enforce async-all-the-way pattern through code review and static analysis. Use APM tools to monitor async operation latency and thread pool exhaustion. + Owner: engineering team +- Command-query separation may be violated by developers unfamiliar with the pattern, leading to inconsistent API boundary implementations + Mitigation: Document pattern in architectural guidelines with code examples. Use architectural fitness functions or linting rules to detect direct data access from controllers. + Owner: engineering team + +## Implementation Notes + +- Define command interfaces with single-responsibility methods (e.g., IDestroySceneCommand.DestroyAsync) and query interfaces for read operations, injecting them into controllers via constructor dependency injection +- Use Microsoft.AspNetCore.Mvc attributes ([HttpPost], [HttpDelete], [FromBody], [FromRoute]) to declare HTTP boundaries and parameter binding, ensuring all action methods return Task +- Implement structured error handling with try-catch blocks that distinguish AggregateException (batch operations) from domain exceptions (SceneExecutionException), returning BadRequest with error details +- Add structured logging at API boundary entry points using ILogger with semantic context (logger.LogInformation with PlayIds, Template parameters) for operation traceability + +## Continuation Context + + +Verify commands: +- grep -r "public.*Controller" --include="*.cs" | xargs -I {} sh -c 'grep -L "async Task" {} && echo "Missing async pattern: {}"' +- grep -r "class.*Controller" --include="*.cs" -A 50 | grep -E "(DbContext|SaveChanges|Query\(|Execute\()" | grep -v "//" && echo "Direct data access detected in controller" +- find . -name "*Controller.cs" -exec grep -l "await.*\(Async\|ExecuteAsync\|DestroyAsync\)" {} \; | wc -l + +Accept when: +- All API controller action methods use async Task signatures and await command/query interface methods rather than performing direct data access +- Grep verification finds no DbContext or direct persistence operations within controller class bodies (excluding comments) +- At least 80% of controller files contain async/await patterns with interface method invocations (ExecuteAsync, DestroyAsync, or similar) + +## Enforcement + +- Verified by: Code review checklist requiring command-query interface usage in all new API controllers +- Verified by: Static analysis rules detecting direct DbContext or data access usage within controller classes +- Verified by: Integration tests validating async execution patterns and error handling at API boundaries +- Violation handling: Pull requests with direct data access in controllers are rejected with reference to this ADR +- Violation handling: Static analysis violations block CI pipeline until resolved or explicitly exempted +- Violation handling: Architectural review required for any controller that does not follow command-query separation pattern +- Exception process: Document technical justification for exception in ADR amendment or inline code comments +- Exception process: Obtain approval from technical lead or architect before merging exception +- Exception process: Tag exceptional code with [ADR-AUTO-EXCEPTION] comment and link to justification \ No newline at end of file diff --git a/docs/adr/b50c1537-803a-4460-8c5d-49b40744ec96-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-received.md b/docs/adr/b50c1537-803a-4460-8c5d-49b40744ec96-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-received.md new file mode 100644 index 000000000000..8515c3e02a9b --- /dev/null +++ b/docs/adr/b50c1537-803a-4460-8c5d-49b40744ec96-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-use-received.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Use Received + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. MUST: Tests MUST use Received() verification on mocked dependencies after awaiting the system-under-test invocation to ensure call order verification + +## Policy Block + +- MUST Tests MUST use Received() verification on mocked dependencies after awaiting the system-under-test invocation to ensure call order verification + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/b569cad3-d31f-4e1c-b491-858e64c8d8bf-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-returning.md b/docs/adr/b569cad3-d31f-4e1c-b491-858e64c8d8bf-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-returning.md new file mode 100644 index 000000000000..fda0014b221d --- /dev/null +++ b/docs/adr/b569cad3-d31f-4e1c-b491-858e64c8d8bf-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-ffi-functions-returning.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Ffi Functions Returning + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. MUST: FFI functions returning strings to C callers MUST use std::ffi::CString and provide a corresponding free_c_string function to prevent memory leaks + +## Policy Block + +- MUST FFI functions returning strings to C callers MUST use std::ffi::CString and provide a corresponding free_c_string function to prevent memory leaks + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/b56acf9d-5917-4557-8014-57020819af23-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-key-generation.md b/docs/adr/b56acf9d-5917-4557-8014-57020819af23-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-key-generation.md new file mode 100644 index 000000000000..1af56b57d4f4 --- /dev/null +++ b/docs/adr/b56acf9d-5917-4557-8014-57020819af23-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-key-generation.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Key Generation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. MUST: All cryptographic key generation functions exposed through FFI MUST use c_char pointers with explicit CString/CStr conversions for string parameters + +## Policy Block + +- MUST All cryptographic key generation functions exposed through FFI MUST use c_char pointers with explicit CString/CStr conversions for string parameters + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/b5a143c2-0481-4e32-8cb8-cfafca5ce423-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md b/docs/adr/b5a143c2-0481-4e32-8cb8-cfafca5ce423-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md new file mode 100644 index 000000000000..8a7e8fa62b72 --- /dev/null +++ b/docs/adr/b5a143c2-0481-4e32-8cb8-cfafca5ce423-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-service-registration.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Service Registration + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. MUST: Cache service registration MUST be performed through the ExtendedCacheServiceCollectionExtensions.AddExtendedCache extension method in Bit.Core.Utilities + +## Policy Block + +- MUST Cache service registration MUST be performed through the ExtendedCacheServiceCollectionExtensions.AddExtendedCache extension method in Bit.Core.Utilities + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/b5aa68ab-f345-4b09-b35f-327118015892-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-self-modification-operations.md b/docs/adr/b5aa68ab-f345-4b09-b35f-327118015892-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-self-modification-operations.md new file mode 100644 index 000000000000..612b39418773 --- /dev/null +++ b/docs/adr/b5aa68ab-f345-4b09-b35f-327118015892-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-self-modification-operations.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Self Modification Operations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. MUST_NOT: Self-modification operations MUST_NOT allow users to grant themselves permissions to collections when AllowAdminAccessToAllCollectionItems is disabled + +## Policy Block + +- MUST_NOT Self-modification operations MUST_NOT allow users to grant themselves permissions to collections when AllowAdminAccessToAllCollectionItems is disabled + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/b5d99c3b-d0d8-4d81-bcde-af3fcc76ee3f-enforce-organization-scoped-authorization-requirements-for-billing-operations-billing-endpoints-that.md b/docs/adr/b5d99c3b-d0d8-4d81-bcde-af3fcc76ee3f-enforce-organization-scoped-authorization-requirements-for-billing-operations-billing-endpoints-that.md new file mode 100644 index 000000000000..cdc1f5170a42 --- /dev/null +++ b/docs/adr/b5d99c3b-d0d8-4d81-bcde-af3fcc76ee3f-enforce-organization-scoped-authorization-requirements-for-billing-operations-billing-endpoints-that.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Billing Endpoints That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. MUST: Billing endpoints that modify organization state (subscription updates, billing address changes, payment method updates) MUST enforce the same authorization requirement as read operations + +## Policy Block + +- MUST Billing endpoints that modify organization state (subscription updates, billing address changes, payment method updates) MUST enforce the same authorization requirement as read operations + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/b65c1be4-a418-4582-bdb0-f734ba86efc4-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-combine.md b/docs/adr/b65c1be4-a418-4582-bdb0-f734ba86efc4-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-combine.md new file mode 100644 index 000000000000..080de7769c09 --- /dev/null +++ b/docs/adr/b65c1be4-a418-4582-bdb0-f734ba86efc4-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-combine.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Combine + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MAY: Authorization policies MAY combine multiple requirements (authentication, claims, assertions) within a single named policy + +## Policy Block + +- MAY Authorization policies MAY combine multiple requirements (authentication, claims, assertions) within a single named policy + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/b6700091-00ec-4e70-84f3-648c1a9bb652-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-ffi-exposed-cryptographic.md b/docs/adr/b6700091-00ec-4e70-84f3-648c1a9bb652-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-ffi-exposed-cryptographic.md new file mode 100644 index 000000000000..d61774f4655b --- /dev/null +++ b/docs/adr/b6700091-00ec-4e70-84f3-648c1a9bb652-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-ffi-exposed-cryptographic.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Ffi Exposed Cryptographic + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. MUST: FFI-exposed cryptographic functions that accept key material MUST have corresponding test cases using the standardized fake RSA keys + +## Policy Block + +- MUST FFI-exposed cryptographic functions that accept key material MUST have corresponding test cases using the standardized fake RSA keys + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/b69528d8-c594-445d-b5fb-9410756a89c7-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-typed-requirement-classes.md b/docs/adr/b69528d8-c594-445d-b5fb-9410756a89c7-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-typed-requirement-classes.md new file mode 100644 index 000000000000..70adfcc60b2a --- /dev/null +++ b/docs/adr/b69528d8-c594-445d-b5fb-9410756a89c7-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-typed-requirement-classes.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Typed Requirement Classes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. MUST: Typed requirement classes MUST be defined in the Bit.Api.AdminConsole.Authorization namespace or its subnamespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements) + +## Policy Block + +- MUST Typed requirement classes MUST be defined in the Bit.Api.AdminConsole.Authorization namespace or its subnamespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements) + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/b774d498-b072-4740-8391-71e62deb6dd4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-registration-encapsulated.md b/docs/adr/b774d498-b072-4740-8391-71e62deb6dd4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-registration-encapsulated.md new file mode 100644 index 000000000000..17907b5e846e --- /dev/null +++ b/docs/adr/b774d498-b072-4740-8391-71e62deb6dd4-use-redis-via-stackexchangeredis-for-distributed-caching-with-extended-cache-utilities-cache-registration-encapsulated.md @@ -0,0 +1,121 @@ +# Use Redis via StackExchangeRedis for Distributed Caching with Extended Cache Utilities: Cache Registration Encapsulated + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase requires distributed caching capabilities to support scalable, multi-instance deployments where in-memory caching is insufficient +- Redis is integrated through StackExchangeRedis and Microsoft.Extensions.Caching.Distributed abstractions to provide a standardized caching interface +- Extended cache utilities in Bit.Core.Utilities provide custom service collection extensions that wrap Redis connection management and error handling +- Connection failures to Redis are logged with structured logging using Microsoft.Extensions.Logging to enable operational visibility +- The pattern appears in ExtendedCacheServiceCollectionExtensions.cs which coordinates dependency injection registration for distributed cache implementations + +## Problem Statement + +Applications requiring horizontal scaling need a shared caching layer that persists beyond individual process lifetimes, but direct Redis integration introduces connection management complexity, error handling concerns, and tight coupling to infrastructure configuration that must be abstracted for maintainability and testability. + +## Decision + +1. SHOULD: Cache registration SHOULD be encapsulated in service collection extension methods (e.g., AddExtendedCache) within Bit.Core.Utilities + +## Policy Block + +- SHOULD Cache registration SHOULD be encapsulated in service collection extension methods (e.g., AddExtendedCache) within Bit.Core.Utilities + +In scope: +- All distributed caching requirements in Bit.Core and dependent services +- Redis-backed cache implementations registered through dependency injection +- Service collection extensions in Bit.Core.Utilities namespace +- Connection management and error handling for Redis cache instances + +Out of scope: +- In-memory caching for single-instance or development scenarios +- Other distributed cache providers (e.g., SQL Server, NCache) unless wrapped in IDistributedCache +- Direct Redis usage for non-caching purposes (e.g., pub/sub, streams) +- Client-side caching or browser storage mechanisms + +Exceptions: +- EXC-001: Performance profiling or debugging requires direct Redis client access to inspect connection state or execute raw commands + +## Rationale + +- The evidence shows explicit usage of StackExchangeRedis and Microsoft.Extensions.Caching.Distributed in ExtendedCacheServiceCollectionExtensions.cs, indicating a deliberate abstraction layer over Redis +- Structured error logging with cache name context (LogError with 'Failed to connect to Redis for cache {CacheName}') demonstrates operational maturity and debugging support +- The use of Bit.Core.Utilities and Bit.Core.Settings namespaces indicates centralized configuration management and reusable infrastructure patterns +- Public API surface (ExtendedCacheServiceCollectionExtensions, AddExtendedCache) suggests this is a standardized pattern intended for consumption across multiple services + +## Consequences + +Positive: +- Abstraction through IDistributedCache enables testing with in-memory implementations and potential migration to alternative cache providers +- Centralized connection management in service collection extensions reduces boilerplate and ensures consistent error handling across services +- Structured logging with cache name context improves operational visibility and incident response for cache-related failures +- Dependency injection integration allows for proper lifetime management and configuration injection following .NET conventions + +Negative: +- Additional abstraction layer introduces indirection that may complicate debugging of Redis-specific issues or performance characteristics +- Dependency on StackExchangeRedis couples the codebase to a specific Redis client library, requiring migration effort if the library is deprecated +- Extended cache utilities in Bit.Core.Utilities create a custom framework layer that new developers must learn beyond standard .NET caching patterns +- Connection failure logging may generate noise in logs if Redis is temporarily unavailable, requiring log filtering or alerting tuning + +## Alternatives + +- Use in-memory caching (IMemoryCache) without distributed cache layer (rejected) + Rejected because: In-memory caching does not support multi-instance deployments and loses cache state on process restart, incompatible with horizontal scaling requirements + When valid: Single-instance deployments or development environments where cache consistency across instances is not required +- Direct Redis client usage without IDistributedCache abstraction (rejected) + Rejected because: Direct client usage creates tight coupling to Redis, complicates testing, and prevents future migration to alternative cache providers without significant refactoring + When valid: Scenarios requiring Redis-specific features (pub/sub, streams, transactions) that are not supported by IDistributedCache interface +- Use alternative distributed cache providers (SQL Server, NCache, Azure Cache) (deferred) + Rejected because: Not rejected; the IDistributedCache abstraction allows for future evaluation of alternative providers if Redis proves insufficient + When valid: If Redis operational complexity, licensing, or performance characteristics become problematic, or if cloud-native cache services offer better integration + +## Risks + +- Redis connection failures cause cascading service degradation if cache dependencies are not handled gracefully with fallback logic + Mitigation: Implement circuit breaker patterns, cache-aside with fallback to source data, and ensure services degrade gracefully when cache is unavailable + Owner: Engineering team and SRE +- StackExchangeRedis library vulnerabilities or deprecation could require emergency migration or security patching + Mitigation: Monitor library security advisories, maintain up-to-date dependencies, and document migration path to alternative Redis clients or cache providers + Owner: Security team and engineering team +- Custom extended cache utilities in Bit.Core.Utilities may diverge from standard .NET caching patterns, increasing onboarding friction and maintenance burden + Mitigation: Document extended cache utilities thoroughly, align with .NET conventions where possible, and periodically review for opportunities to adopt standard patterns + Owner: Architecture team + +## Implementation Notes + +- Register distributed cache using AddExtendedCache extension method in service collection configuration, providing Redis connection string from Bit.Core.Settings +- Inject IDistributedCache into services requiring caching, using GetAsync/SetAsync methods with appropriate expiration policies +- Ensure connection string configuration includes retry policies and timeout settings appropriate for production Redis deployments +- Implement cache key naming conventions to avoid collisions across services and enable cache invalidation strategies +- Monitor Redis connection health and cache hit/miss rates using structured logging and application performance monitoring tools + +## Continuation Context + + +Verify commands: +- grep -r 'using Microsoft.Extensions.Caching.Distributed' --include='*.cs' | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'IDistributedCache' --include='*.cs' | grep -v 'using' | head -20 +- grep -r 'AddExtendedCache' --include='*.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' + +Accept when: +- All distributed cache usage in the codebase uses IDistributedCache interface rather than direct Redis client references +- Service collection registration for distributed cache is performed through AddExtendedCache or similar extension methods in Bit.Core.Utilities +- Redis connection failures are logged with structured logging including cache name context +- No direct StackExchangeRedis client usage exists outside of ExtendedCacheServiceCollectionExtensions or designated infrastructure layer + +## Enforcement + +- Verified by: Code review checklist verifying IDistributedCache usage and proper service collection registration +- Verified by: Static analysis rules detecting direct Redis client usage outside infrastructure layer +- Verified by: Integration tests validating cache behavior with both Redis and in-memory implementations +- Verified by: Architecture decision record compliance audits during sprint retrospectives +- Violation handling: Pull requests introducing direct Redis client usage outside infrastructure layer are blocked pending refactoring +- Violation handling: Existing violations are tracked as technical debt items and prioritized for remediation +- Violation handling: Architecture team provides guidance on proper IDistributedCache usage patterns for non-compliant code +- Exception process: Request exception through architecture team with documented justification for Redis-specific feature requirements +- Exception process: Time-box exceptions with explicit removal or refactoring plan +- Exception process: Document approved exceptions in ADR amendments with rationale and scope limitations \ No newline at end of file diff --git a/docs/adr/b7a378ff-2230-4630-bcae-4b368ef2174f-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-registered.md b/docs/adr/b7a378ff-2230-4630-bcae-4b368ef2174f-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-registered.md new file mode 100644 index 000000000000..cd953046f8db --- /dev/null +++ b/docs/adr/b7a378ff-2230-4630-bcae-4b368ef2174f-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-policies-registered.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Policies Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MUST: Authorization policies MUST be registered using services.AddAuthorization() during service configuration in Startup.cs or equivalent application factory classes + +## Policy Block + +- MUST Authorization policies MUST be registered using services.AddAuthorization() during service configuration in Startup.cs or equivalent application factory classes + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/b862eccf-5190-4192-b73e-c7cee246b8c3-adopt-http-client-abstraction-for-external-service-integration-http-client-configurations.md b/docs/adr/b862eccf-5190-4192-b73e-c7cee246b8c3-adopt-http-client-abstraction-for-external-service-integration-http-client-configurations.md new file mode 100644 index 000000000000..33e5ae17abed --- /dev/null +++ b/docs/adr/b862eccf-5190-4192-b73e-c7cee246b8c3-adopt-http-client-abstraction-for-external-service-integration-http-client-configurations.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Http Client Configurations + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. SHOULD: HTTP client configurations SHOULD include timeout policies, retry logic, and circuit breaker patterns for resilient external service integration + +## Policy Block + +- SHOULD HTTP client configurations SHOULD include timeout policies, retry logic, and circuit breaker patterns for resilient external service integration + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/b97877a2-3da0-42cb-812b-54c702b80a92-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-parameters-billing.md b/docs/adr/b97877a2-3da0-42cb-812b-54c702b80a92-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-parameters-billing.md new file mode 100644 index 000000000000..c8823e5d8dfa --- /dev/null +++ b/docs/adr/b97877a2-3da0-42cb-812b-54c702b80a92-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-parameters-billing.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Parameters Billing + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. MUST: Organization parameters in billing endpoints MUST be marked with [BindNever] to prevent client-supplied organization data from bypassing authorization checks + +## Policy Block + +- MUST Organization parameters in billing endpoints MUST be marked with [BindNever] to prevent client-supplied organization data from bypassing authorization checks + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/ba44ca4f-2765-4398-b3c4-113ea2bab4dd-adopt-test-authentication-scheme-for-integration-testing-test-authentication-schemes.md b/docs/adr/ba44ca4f-2765-4398-b3c4-113ea2bab4dd-adopt-test-authentication-scheme-for-integration-testing-test-authentication-schemes.md new file mode 100644 index 000000000000..04ab0fa650e9 --- /dev/null +++ b/docs/adr/ba44ca4f-2765-4398-b3c4-113ea2bab4dd-adopt-test-authentication-scheme-for-integration-testing-test-authentication-schemes.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Schemes + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. SHOULD: Test authentication schemes SHOULD use a distinct scheme name (e.g., "Test") to differentiate from production schemes + +## Policy Block + +- SHOULD Test authentication schemes SHOULD use a distinct scheme name (e.g., "Test") to differentiate from production schemes + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/bbc83d26-64c4-4e7c-a505-7a9b2665a645-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-components-cipher.md b/docs/adr/bbc83d26-64c4-4e7c-a505-7a9b2665a645-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-components-cipher.md new file mode 100644 index 000000000000..cd45da39e4b2 --- /dev/null +++ b/docs/adr/bbc83d26-64c4-4e7c-a505-7a9b2665a645-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-components-cipher.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Components Cipher + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. SHOULD: Cryptographic components (cipher, rsa_keys) SHOULD have dedicated test mocks to validate behavior in isolation + +## Policy Block + +- SHOULD Cryptographic components (cipher, rsa_keys) SHOULD have dedicated test mocks to validate behavior in isolation + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/bc29ebf0-457a-4663-9f3e-02531612373e-establish-http-client-boundaries-for-external-service-integration-test-environments-use.md b/docs/adr/bc29ebf0-457a-4663-9f3e-02531612373e-establish-http-client-boundaries-for-external-service-integration-test-environments-use.md new file mode 100644 index 000000000000..8189b0960223 --- /dev/null +++ b/docs/adr/bc29ebf0-457a-4663-9f3e-02531612373e-establish-http-client-boundaries-for-external-service-integration-test-environments-use.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: Test Environments Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. SHOULD: Test environments SHOULD use custom authentication handlers (e.g., TestAuthHandler) to simulate external authentication without network calls + +## Policy Block + +- SHOULD Test environments SHOULD use custom authentication handlers (e.g., TestAuthHandler) to simulate external authentication without network calls + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/bc7e164b-099b-4ba0-8e7e-c50e8ff13166-adopt-test-authentication-scheme-for-integration-testing-integration-test-projects.md b/docs/adr/bc7e164b-099b-4ba0-8e7e-c50e8ff13166-adopt-test-authentication-scheme-for-integration-testing-integration-test-projects.md new file mode 100644 index 000000000000..b01f6469acc2 --- /dev/null +++ b/docs/adr/bc7e164b-099b-4ba0-8e7e-c50e8ff13166-adopt-test-authentication-scheme-for-integration-testing-integration-test-projects.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Integration Test Projects + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. MUST: Integration test projects MUST call AddAuthentication() to register authentication schemes in the service collection + +## Policy Block + +- MUST Integration test projects MUST call AddAuthentication() to register authentication schemes in the service collection + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/bd635931-0c61-4030-8a96-afebe0b1149c-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-test-environments-define.md b/docs/adr/bd635931-0c61-4030-8a96-afebe0b1149c-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-test-environments-define.md new file mode 100644 index 000000000000..5f3e063e18e9 --- /dev/null +++ b/docs/adr/bd635931-0c61-4030-8a96-afebe0b1149c-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-test-environments-define.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Test Environments Define + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. SHOULD: Test environments SHOULD define separate authorization policies using policy.RequireAssertion() to bypass production authorization requirements + +## Policy Block + +- SHOULD Test environments SHOULD define separate authorization policies using policy.RequireAssertion() to bypass production authorization requirements + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/bd9c0591-a386-4d5e-a80d-763893e0e961-standardize-authorization-policy-configuration-with-named-scopes-scope-based-authorization.md b/docs/adr/bd9c0591-a386-4d5e-a80d-763893e0e961-standardize-authorization-policy-configuration-with-named-scopes-scope-based-authorization.md new file mode 100644 index 000000000000..ca5b2efeee6e --- /dev/null +++ b/docs/adr/bd9c0591-a386-4d5e-a80d-763893e0e961-standardize-authorization-policy-configuration-with-named-scopes-scope-based-authorization.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Scope Based Authorization + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. MUST: API scope-based authorization MUST use RequireClaim with JwtClaimTypes.Scope to enforce scope requirements + +## Policy Block + +- MUST API scope-based authorization MUST use RequireClaim with JwtClaimTypes.Scope to enforce scope requirements + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/be91c795-209c-4756-a476-c7299c3bd4f9-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-fixtures-requiring.md b/docs/adr/be91c795-209c-4756-a476-c7299c3bd4f9-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-fixtures-requiring.md new file mode 100644 index 000000000000..8f3b54dc9cd7 --- /dev/null +++ b/docs/adr/be91c795-209c-4756-a476-c7299c3bd4f9-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-test-fixtures-requiring.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Test Fixtures Requiring + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. SHOULD: Test fixtures requiring multiple distinct key pairs SHOULD use numbered sequences (_FAKE_RSA_KEY_0, _FAKE_RSA_KEY_1, etc.) to provide clear identification + +## Policy Block + +- SHOULD Test fixtures requiring multiple distinct key pairs SHOULD use numbered sequences (_FAKE_RSA_KEY_0, _FAKE_RSA_KEY_1, etc.) to provide clear identification + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/bee1ce59-2afa-4c78-a877-66249177f453-enforce-authorization-attributes-on-api-controllers-via-unit-tests-unit-tests-use.md b/docs/adr/bee1ce59-2afa-4c78-a877-66249177f453-enforce-authorization-attributes-on-api-controllers-via-unit-tests-unit-tests-use.md new file mode 100644 index 000000000000..b2983a320a1f --- /dev/null +++ b/docs/adr/bee1ce59-2afa-4c78-a877-66249177f453-enforce-authorization-attributes-on-api-controllers-via-unit-tests-unit-tests-use.md @@ -0,0 +1,120 @@ +# Enforce Authorization Attributes on API Controllers via Unit Tests: Unit Tests Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- API controllers in Microsoft.AspNetCore.Mvc expose HTTP endpoints that require authorization to prevent unauthorized access to protected resources +- Authorization attributes can be applied at class level ([Authorize]) or method level (custom authorization attributes), creating multiple points where security configuration must be validated +- Manual code review of authorization attributes across controllers is error-prone and does not scale as the number of controllers and HTTP methods grows +- Unit tests using reflection can systematically verify that all HTTP action methods have appropriate authorization attributes, catching missing security configurations before deployment +- The codebase uses Xunit as the testing framework and Microsoft.AspNetCore.Authorization for authorization infrastructure + +## Problem Statement + +API controllers may expose HTTP endpoints without proper authorization attributes, creating security vulnerabilities where unauthorized users can access protected resources. Without automated verification, developers may inadvertently omit class-level [Authorize] attributes or method-level authorization on individual HTTP actions (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch), leading to inconsistent security posture across the API surface. + +## Decision + +1. MUST: Unit tests MUST use reflection-based helpers to verify authorization attributes on all controllers + +## Policy Block + +- MUST Unit tests MUST use reflection-based helpers to verify authorization attributes on all controllers + +In scope: +- All controllers inheriting from Microsoft.AspNetCore.Mvc controller base classes +- All public methods decorated with HTTP method attributes (HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch) +- Authorization attributes from Microsoft.AspNetCore.Authorization and custom authorization implementations +- Unit test projects using Xunit framework + +Out of scope: +- Non-HTTP public methods on controllers +- Internal or private controller methods +- Authorization logic implementation details (only attribute presence is verified) +- Runtime authorization behavior or policy evaluation +- Integration or end-to-end authorization testing + +Exceptions: +- EXC-001: Public API endpoints that are intentionally anonymous (e.g., health checks, public documentation) + +## Rationale + +- Evidence shows ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization validates both class-level and method-level authorization, catching configuration gaps at build time +- Test cases demonstrate detection of missing class-level [Authorize] attributes and unauthorized HTTP methods (GetUnauthorized, PostUnauthorized, PutUnauthorized), proving the pattern prevents security misconfigurations +- Reflection-based verification in unit tests provides fast feedback during development without requiring deployed environments or integration test infrastructure +- Swagger document validation (CheckDuplicateOperationIdsDocumentFilter) complements authorization testing by ensuring API surface consistency and preventing ambiguous endpoint definitions + +## Consequences + +Positive: +- Security vulnerabilities from missing authorization attributes are caught during unit test execution before code reaches production +- Developers receive immediate, specific feedback identifying which controllers and methods lack authorization +- Consistent authorization enforcement across all API endpoints reduces attack surface +- Automated verification scales efficiently as the number of controllers grows without increasing manual review burden + +Negative: +- Reflection-based tests add maintenance overhead when authorization patterns change or new attribute types are introduced +- Test failures may create friction in development workflow if authorization requirements are not clearly documented +- False positives may occur if legitimate anonymous endpoints are not properly marked with [AllowAnonymous] +- Unit tests verify attribute presence but cannot validate runtime authorization policy correctness or effectiveness + +## Alternatives + +- Manual code review of authorization attributes during pull request review (rejected) + Rejected because: Manual review does not scale, is error-prone, and provides delayed feedback compared to automated unit tests that run on every build + When valid: May be used as supplementary validation for complex authorization logic beyond attribute presence +- Static analysis tools or custom Roslyn analyzers to detect missing authorization attributes (deferred) + Rejected because: Not rejected but not currently implemented; would provide IDE-integrated feedback but requires additional tooling investment + When valid: Could complement unit tests by providing real-time feedback during code authoring +- Integration tests that attempt unauthorized access to endpoints (rejected) + Rejected because: Integration tests are slower, require deployed environments, and provide less specific feedback about which attributes are missing compared to reflection-based unit tests + When valid: Should be used to validate runtime authorization behavior but not as primary mechanism for detecting missing attributes + +## Risks + +- Test helpers may not detect new HTTP method attributes or custom authorization patterns introduced in future framework versions + Mitigation: Regularly review and update ControllerAuthorizationTestHelpers to support new HTTP method attributes; monitor framework release notes for authorization changes + Owner: API security team +- Developers may add [AllowAnonymous] to bypass test failures without proper security review + Mitigation: Implement code review checks for [AllowAnonymous] usage; require security team approval for anonymous endpoints; document exception process in policy + Owner: Security team and code reviewers +- Reflection-based tests may become brittle if controller inheritance hierarchies or attribute application patterns change + Mitigation: Maintain comprehensive test coverage of ControllerAuthorizationTestHelpers itself; use test cases for edge cases like inheritance and attribute combinations + Owner: Engineering team + +## Implementation Notes + +- Create a base test class or shared test helper that all controller test classes can invoke to verify authorization attributes +- Use ControllerAuthorizationTestHelpers.AssertAllHttpMethodsHaveAuthorization pattern: pass controller type, method throws FailException with descriptive message on violations +- Include test cases for both positive scenarios (properly authorized controllers) and negative scenarios (missing class-level or method-level attributes) to validate test helper behavior +- For Swagger/OpenAPI validation, apply CheckDuplicateOperationIdsDocumentFilter in Swagger configuration to catch duplicate operation IDs at application startup or in tests +- Document authorization requirements and exception process in team guidelines so developers understand when [AllowAnonymous] is appropriate + +## Continuation Context + + +Verify commands: +- grep -r 'AssertAllHttpMethodsHaveAuthorization' test/ --include='*.cs' | wc -l +- dotnet test --filter 'FullyQualifiedName~ControllerAuthorizationTestHelpers' --no-build +- grep -r '\[Authorize\]' src/ --include='*Controller.cs' | wc -l + +Accept when: +- All controller test files invoke AssertAllHttpMethodsHaveAuthorization for their respective controller types +- Unit tests pass for all controllers, confirming class-level [Authorize] and method-level authorization attributes are present +- Grep commands show authorization test coverage exists and [Authorize] attributes are consistently applied across controllers + +## Enforcement + +- Verified by: Automated unit test execution in CI pipeline fails builds when authorization attributes are missing +- Verified by: Code coverage reports track execution of authorization verification tests +- Verified by: Pull request checks require passing unit tests including authorization verification +- Violation handling: CI build fails with Xunit.Sdk.FailException identifying specific controllers and methods missing authorization +- Violation handling: Pull requests cannot merge until authorization tests pass +- Violation handling: Security team is notified of repeated violations or attempts to bypass tests +- Exception process: Developer documents rationale for anonymous endpoint in controller comments and ADR exception request +- Exception process: Security team reviews exception request and approves or rejects based on risk assessment +- Exception process: Approved exceptions use [AllowAnonymous] attribute and are documented in security review records +- Exception process: Exception list is reviewed quarterly to ensure anonymous endpoints remain appropriate \ No newline at end of file diff --git a/docs/adr/bf2ab4ec-7f8d-492a-b356-25c2f0b9eac4-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md b/docs/adr/bf2ab4ec-7f8d-492a-b356-25c2f0b9eac4-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md new file mode 100644 index 000000000000..044caa308490 --- /dev/null +++ b/docs/adr/bf2ab4ec-7f8d-492a-b356-25c2f0b9eac4-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-accepting.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Accepting + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. MUST: All FFI functions accepting c_char pointer parameters MUST validate input using CStr::from_ptr or equivalent before dereferencing + +## Policy Block + +- MUST All FFI functions accepting c_char pointer parameters MUST validate input using CStr::from_ptr or equivalent before dereferencing + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/bf81a88a-0c42-4cb9-b420-079805d48869-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-not.md b/docs/adr/bf81a88a-0c42-4cb9-b420-079805d48869-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-not.md new file mode 100644 index 000000000000..092a919a0f13 --- /dev/null +++ b/docs/adr/bf81a88a-0c42-4cb9-b420-079805d48869-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-not.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Entries Not + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. MUST_NOT: Log entries MUST NOT include sensitive authentication tokens, passwords, payment details, or personally identifiable information beyond resource identifiers + +## Policy Block + +- MUST_NOT Log entries MUST NOT include sensitive authentication tokens, passwords, payment details, or personally identifiable information beyond resource identifiers + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/bfc4a3c9-a71f-4235-8343-7602daa8576c-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md b/docs/adr/bfc4a3c9-a71f-4235-8343-7602daa8576c-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md new file mode 100644 index 000000000000..fe0e272135a5 --- /dev/null +++ b/docs/adr/bfc4a3c9-a71f-4235-8343-7602daa8576c-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-fake-rsa-key.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Fake Rsa Key + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. MUST: Fake RSA key constants MUST be declared with `const` visibility and MUST NOT be exported from the module's public API. + +## Policy Block + +- MUST Fake RSA key constants MUST be declared with `const` visibility and MUST NOT be exported from the module's public API. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/c0954ece-5f93-4c49-acaf-337ccb671903-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-test-code-define.md b/docs/adr/c0954ece-5f93-4c49-acaf-337ccb671903-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-test-code-define.md new file mode 100644 index 000000000000..9b78baa14ab0 --- /dev/null +++ b/docs/adr/c0954ece-5f93-4c49-acaf-337ccb671903-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-test-code-define.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Test Code Define + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. MAY: Test code MAY define additional fake key constants following the same naming pattern for specialized test scenarios requiring more than 5 key pairs. + +## Policy Block + +- MAY Test code MAY define additional fake key constants following the same naming pattern for specialized test scenarios requiring more than 5 key pairs. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/c0eccdcc-f9f8-4371-85bc-935d747950f8-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-modules-containing-fake.md b/docs/adr/c0eccdcc-f9f8-4371-85bc-935d747950f8-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-modules-containing-fake.md new file mode 100644 index 000000000000..6b9d2aae7042 --- /dev/null +++ b/docs/adr/c0eccdcc-f9f8-4371-85bc-935d747950f8-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-modules-containing-fake.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Modules Containing Fake + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. SHOULD: Modules containing _FAKE_RSA_KEY_* constants SHOULD include automated verification that these constants are never referenced outside test compilation units. + +## Policy Block + +- SHOULD Modules containing _FAKE_RSA_KEY_* constants SHOULD include automated verification that these constants are never referenced outside test compilation units. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/c368c23f-80fd-4b43-8ae5-2c4f9d2cb067-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-production-code-paths.md b/docs/adr/c368c23f-80fd-4b43-8ae5-2c4f9d2cb067-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-production-code-paths.md new file mode 100644 index 000000000000..72c52c5fae99 --- /dev/null +++ b/docs/adr/c368c23f-80fd-4b43-8ae5-2c4f9d2cb067-isolate-hardcoded-rsa-private-keys-to-test-only-constants-with-naming-convention-production-code-paths.md @@ -0,0 +1,124 @@ +# Isolate Hardcoded RSA Private Keys to Test-Only Constants with Naming Convention: Production Code Paths + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all Rust SDK modules containing cryptographic test fixtures. + +## Context + +- The Rust SDK requires RSA key material for testing cryptographic operations without accessing real production keys or external key management systems. +- Test suites need deterministic, reproducible key pairs to validate signing, encryption, and key rotation logic across multiple test scenarios. +- Hardcoded private keys in production code pose severe security risks, requiring clear isolation mechanisms to prevent accidental deployment or misuse. +- The codebase uses a naming convention (_FAKE_RSA_KEY_N) to signal test-only usage, but lacks enforcement mechanisms to prevent these constants from being referenced outside test contexts. +- Multiple fake RSA keys (0-4) are defined as string constants containing PEM-encoded PKCS#8 private keys, suggesting test coverage for key rotation or multi-key scenarios. + +## Problem Statement + +Hardcoded RSA private keys in source code create security vulnerabilities if accidentally used in production, leaked through version control, or referenced by non-test code. Without compile-time or runtime enforcement, naming conventions alone cannot prevent misuse of test cryptographic material in security-sensitive contexts. + +## Decision + +1. MUST_NOT: Production code paths MUST NOT reference _FAKE_RSA_KEY_* constants; references are permitted only within #[cfg(test)] blocks or test-only modules. + +## Policy Block + +- MUST_NOT Production code paths MUST NOT reference _FAKE_RSA_KEY_* constants; references are permitted only within #[cfg(test)] blocks or test-only modules. + +In scope: +- All Rust modules in util/RustSdk/rust/src/ containing cryptographic test fixtures +- Test helper modules that provide mock cryptographic material for integration tests +- CI/CD verification scripts that scan for hardcoded cryptographic material + +Out of scope: +- Production cryptographic key management systems or secret stores +- Runtime key generation or key derivation functions used in production code +- External test fixtures loaded from files or environment variables +- Non-RSA cryptographic algorithms (e.g., ECDSA, Ed25519) which may use different naming conventions + +Exceptions: +- EXC-001: A test module requires non-standard key formats (e.g., SSH format, JWK) for interoperability testing + +## Rationale + +- The evidence shows 5 distinct fake RSA keys defined with consistent naming (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4), indicating an established pattern for test key management in the Rust SDK. +- PEM-encoded PKCS#8 format is the standard representation for RSA private keys in Rust cryptographic libraries, making this format appropriate for test fixtures that exercise real cryptographic APIs. +- The naming convention with _FAKE_ prefix provides human-readable signal of test-only usage, but requires enforcement through code review, static analysis, or compilation guards to prevent production misuse. +- Multiple keys suggest test coverage for scenarios like key rotation, multi-party signing, or algorithm compatibility testing, which are valid testing requirements for cryptographic SDKs. + +## Consequences + +Positive: +- Test suites gain deterministic, version-controlled cryptographic fixtures that enable reproducible testing without external dependencies. +- Clear naming convention makes it immediately obvious during code review when test-only cryptographic material is being referenced. +- Consolidating fake keys in a single module (rsa_keys.rs) creates a single audit point for test cryptographic material. +- Multiple pre-generated keys enable comprehensive testing of key rotation and multi-key scenarios without runtime key generation overhead. + +Negative: +- Hardcoded private keys in source code increase the attack surface if accidentally deployed to production or leaked through version control history. +- Naming conventions alone provide weak enforcement; developers can still accidentally reference _FAKE_RSA_KEY_* constants in production code without compile-time errors. +- Large PEM-encoded keys increase source file size and may trigger security scanning false positives in automated code analysis tools. +- Maintaining multiple fake keys requires coordination to ensure they remain cryptographically valid and distinct across test scenarios. + +## Alternatives + +- Generate RSA key pairs dynamically at test runtime using a seeded random number generator (rejected) + Rejected because: Runtime key generation adds significant overhead to test execution (RSA key generation is computationally expensive) and complicates test reproducibility across different hardware or Rust compiler versions. + When valid: Valid for performance-insensitive integration tests where key uniqueness per test run is required +- Load test keys from external fixture files (e.g., testdata/fake_rsa_key_0.pem) rather than embedding in source code (rejected) + Rejected because: External files complicate test setup, require file I/O during test execution, and create additional failure modes (missing files, incorrect paths) that reduce test reliability. + When valid: Valid for testing file-based key loading logic or when key material exceeds reasonable source code size limits +- Use Rust's type system to create a FakeRsaKey newtype that can only be constructed in test modules via #[cfg(test)] gated constructors (deferred) + Rejected because: Requires significant refactoring of existing test code and cryptographic API surface to accept the newtype, but provides stronger compile-time guarantees against production misuse. + When valid: Should be reconsidered if the codebase adopts a broader type-safe secrets management pattern or if production incidents occur due to test key misuse + +## Risks + +- Developers accidentally reference _FAKE_RSA_KEY_* constants in production code, causing security vulnerabilities or authentication failures. + Mitigation: Implement pre-commit hooks and CI checks that grep for _FAKE_RSA_KEY_ references outside #[cfg(test)] blocks; add clippy lint rules to detect test constant usage in production modules. + Owner: Security team and Rust SDK maintainers +- Fake RSA keys become invalid or corrupted during code refactoring, causing widespread test failures that are difficult to diagnose. + Mitigation: Add unit tests that validate each _FAKE_RSA_KEY_* constant can be successfully parsed and used for basic cryptographic operations (sign/verify round-trip). + Owner: Rust SDK test infrastructure team +- Security scanners flag hardcoded private keys as critical vulnerabilities, creating alert fatigue and potentially masking real security issues. + Mitigation: Configure security scanning tools to allowlist the specific file (rsa_keys.rs) and naming pattern (_FAKE_RSA_KEY_*); document the exception in security scanning runbooks. + Owner: Security operations team + +## Implementation Notes + +- Consolidate all _FAKE_RSA_KEY_* constants into a dedicated test_fixtures module or rsa_keys.rs file to create a single audit point. +- Add inline documentation above each constant explaining its intended test scenario (e.g., '// Used for testing key rotation between _FAKE_RSA_KEY_0 and _FAKE_RSA_KEY_1'). +- Implement a CI verification step that runs `grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude='*test*' --exclude='rsa_keys.rs'` to detect production references. +- Consider adding a build.rs script that validates all _FAKE_RSA_KEY_* constants are valid PEM-encoded PKCS#8 keys at compile time. + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v '#\[cfg(test)\]' | grep -v 'rsa_keys.rs' | grep -v '/tests/' || echo 'No production references found' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key validation tests pass' +- rg 'const.*_FAKE_RSA_KEY_\d+.*BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | wc -l | grep -q '^5$' && echo 'All 5 fake keys present with correct format' + +Accept when: +- All _FAKE_RSA_KEY_* constants are defined in rsa_keys.rs with const visibility and PEM PKCS#8 format +- No references to _FAKE_RSA_KEY_* exist outside #[cfg(test)] blocks or test-only modules +- CI pipeline includes automated checks that fail builds if production code references test key constants +- Each fake key constant includes inline documentation explaining its test scenario + +## Enforcement + +- Verified by: Pre-commit hooks that grep for _FAKE_RSA_KEY_ references outside test contexts +- Verified by: CI/CD pipeline static analysis step that fails builds on policy violations +- Verified by: Quarterly security audits of cryptographic test fixtures and their usage patterns +- Verified by: Code review checklist item requiring verification that new cryptographic tests use approved fake key constants +- Violation handling: CI build failures block merge until _FAKE_RSA_KEY_ references are removed from production code +- Violation handling: Security scanner alerts on hardcoded private keys outside rsa_keys.rs trigger immediate investigation +- Violation handling: Production incidents involving test key material require post-incident review and potential key rotation +- Violation handling: Repeated violations trigger mandatory security training for the responsible developer +- Exception process: Developer submits exception request to security team with justification for non-standard key format or usage +- Exception process: Security team lead and module owner review the cryptographic requirements and risk assessment +- Exception process: Approved exceptions are documented in code comments with EXC-XXX reference and expiration date +- Exception process: All exceptions are reviewed quarterly and must be re-approved or remediated \ No newline at end of file diff --git a/docs/adr/c43d4ce1-3b5f-4e6d-8f9b-8a57664a6f36-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-implementation-suppress-specific.md b/docs/adr/c43d4ce1-3b5f-4e6d-8f9b-8a57664a6f36-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-implementation-suppress-specific.md new file mode 100644 index 000000000000..aa5f348ebd27 --- /dev/null +++ b/docs/adr/c43d4ce1-3b5f-4e6d-8f9b-8a57664a6f36-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-implementation-suppress-specific.md @@ -0,0 +1,116 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Implementation Suppress Specific + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The push notification service (IPushNotificationService) processes notifications from multiple domain entities including AdminConsole, Auth, and NotificationCenter modules within the Bit.Core namespace +- Invalid notification states (invalid notification ID and invalid notification status ID) are encountered during runtime processing and require observable quality gates +- The codebase uses structured logging with ILogger to record warning-level events when validation failures occur during push notification processing +- A pragma warning disable directive (B) is present, indicating intentional suppression of specific compiler or analyzer warnings in this quality-critical path + +## Problem Statement + +Push notification services must detect and record invalid notification states (malformed IDs or invalid status values) at runtime to enable operational visibility, debugging, and quality assurance, while balancing the need to suppress specific static analysis warnings that may conflict with the chosen logging strategy. + +## Decision + +1. MAY: Implementation MAY suppress specific static analysis warnings (pragma warning disable) when the warning conflicts with the established logging quality gate pattern + +## Policy Block + +- MAY Implementation MAY suppress specific static analysis warnings (pragma warning disable) when the warning conflicts with the established logging quality gate pattern + +In scope: +- All implementations of IPushNotificationService interface +- Push notification processing logic handling Bit.Core.NotificationCenter.Entities +- Validation logic for notification IDs and status IDs +- Runtime quality gates for notification state verification + +Out of scope: +- Logging for successful notification processing (use Info or Debug levels) +- Error-level logging for system failures or exceptions +- Validation logic in non-push notification contexts +- Static analysis warning suppression for non-quality-gate purposes + +Exceptions: +- EXC-001: High-frequency notification processing paths where warning-level logging would create excessive log volume + +## Rationale + +- The evidence shows consistent use of ILogger.LogWarning with structured parameters for two distinct invalid notification scenarios, establishing a quality gate pattern for runtime validation +- Push notifications cross multiple domain boundaries (AdminConsole, Auth, NotificationCenter entities), requiring observable validation points to trace failures across module boundaries +- Warning-level logging provides operational visibility without triggering error alerting, appropriate for validation failures that may be recoverable or expected in certain edge cases +- The presence of pragma warning disable B indicates intentional acceptance of static analysis warnings in favor of the runtime observability pattern + +## Consequences + +Positive: +- Operational teams gain visibility into invalid notification states without manual debugging or code instrumentation +- Structured logging with notification IDs enables correlation of validation failures with specific notification instances across distributed logs +- Consistent warning-level logging establishes a quality gate that can be monitored, alerted on, and analyzed for trends +- Cross-module validation failures become observable at the push service boundary, simplifying root cause analysis + +Negative: +- Warning-level logs may accumulate in high-volume notification scenarios, increasing log storage costs and noise +- Suppression of static analysis warnings (pragma disable) reduces compile-time safety checks and may mask related code quality issues +- Developers must maintain discipline to use structured logging templates rather than simpler string concatenation +- The pattern creates a dependency on logging infrastructure availability for quality gate observability + +## Alternatives + +- Use exception throwing for invalid notification states instead of warning-level logging (rejected) + Rejected because: Exceptions would disrupt notification processing flow and trigger error-level alerting for potentially recoverable validation failures, creating operational noise + When valid: When invalid notification states represent unrecoverable errors that should halt processing +- Implement metrics-based counters for invalid notifications without detailed logging (rejected) + Rejected because: Metrics alone lack the contextual detail (specific notification IDs) needed for debugging individual validation failures + When valid: As a complementary approach for high-level trend monitoring alongside detailed logging +- Use Debug-level logging for validation failures (rejected) + Rejected because: Debug-level logs are typically disabled in production, eliminating operational visibility into validation failures + When valid: In development or staging environments where verbose logging is acceptable + +## Risks + +- High-frequency invalid notifications could generate excessive log volume, impacting log infrastructure performance and costs + Mitigation: Implement log sampling or rate limiting for validation warnings if frequency exceeds operational thresholds; monitor log volume metrics + Owner: Platform engineering team +- Pragma warning suppression may mask legitimate code quality issues flagged by static analysis + Mitigation: Document specific warning codes being suppressed; periodically review suppressed warnings to ensure they remain justified + Owner: Code quality team +- Inconsistent application of logging pattern across different notification entity types could create observability gaps + Mitigation: Implement automated verification (linting or testing) to ensure all notification validation paths include structured warning logs + Owner: Engineering team + +## Implementation Notes + +- Use ILogger interface with structured logging templates: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id) +- Apply the pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities +- Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern +- Consider implementing log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform + +## Continuation Context + + +Verify commands: +- grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' +- grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' +- find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; + +Accept when: +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate + +## Enforcement + +- Verified by: Code review checklist requiring structured warning logs for all notification validation failures +- Verified by: Automated grep-based verification in CI pipeline checking for LogWarning patterns in push notification services +- Verified by: Static analysis configuration review to ensure pragma warning suppressions are documented +- Violation handling: Code review rejection if validation failures lack warning-level logging with structured parameters +- Violation handling: CI pipeline warnings if push notification services are modified without corresponding logging verification +- Violation handling: Quarterly audit of pragma warning suppressions to ensure they remain justified and documented +- Exception process: Submit exception request to platform architecture team with performance impact analysis for high-frequency paths +- Exception process: Provide alternative observability mechanism (metrics, sampling strategy) in exception request +- Exception process: Document approved exceptions in service-level README with rationale and compensating controls \ No newline at end of file diff --git a/docs/adr/c5f8d2c9-7e8d-44e2-8502-2f67bf280239-use-system-text-json-for-scim-api-data-access-serialization-scim-integration-tests.md b/docs/adr/c5f8d2c9-7e8d-44e2-8502-2f67bf280239-use-system-text-json-for-scim-api-data-access-serialization-scim-integration-tests.md new file mode 100644 index 000000000000..fd99e0dbac75 --- /dev/null +++ b/docs/adr/c5f8d2c9-7e8d-44e2-8502-2f67bf280239-use-system-text-json-for-scim-api-data-access-serialization-scim-integration-tests.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Scim Integration Tests + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. MUST: SCIM API integration tests MUST use System.Text.Json for serializing request and response payloads + +## Policy Block + +- MUST SCIM API integration tests MUST use System.Text.Json for serializing request and response payloads + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/c6925c30-52cd-4b6a-b3a6-106604368441-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-additional-fake-keys.md b/docs/adr/c6925c30-52cd-4b6a-b3a6-106604368441-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-additional-fake-keys.md new file mode 100644 index 000000000000..7fc115349a54 --- /dev/null +++ b/docs/adr/c6925c30-52cd-4b6a-b3a6-106604368441-use-embedded-fake-rsa-keys-for-testing-public-api-protocols-additional-fake-keys.md @@ -0,0 +1,121 @@ +# Use Embedded Fake RSA Keys for Testing Public API Protocols: Additional Fake Keys + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code that exercises cryptographic operations in public API protocols. + +## Context + +- The Rust SDK module (util/RustSdk/rust/src/rsa_keys.rs) contains multiple embedded RSA private keys prefixed with _FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4, each containing full PEM-encoded 2048-bit RSA private keys +- The build.rs file uses csbindgen to generate C# interop bindings from Rust extern functions, exposing cipher operations and lib.rs exports to a .NET consumer via NativeMethods.g.cs +- The presence of five distinct fake RSA keys suggests testing scenarios that require multiple key pairs for protocol validation, key rotation simulation, or multi-party cryptographic workflows +- The keys are marked with const declarations and appear alongside facet tags (testing.mocking, data.modeling.style, api.public.protocols, security.input_validation), indicating cross-cutting test concerns +- The pattern appears in a cross-language SDK context where Rust cryptographic primitives are exposed to C# consumers, requiring deterministic test fixtures that work across the FFI boundary + +## Problem Statement + +Testing cryptographic operations in public API protocols requires deterministic, reproducible key material that does not expose real secrets, can be safely committed to version control, and works consistently across language boundaries (Rust to C# via FFI). Without standardized fake keys, tests become non-deterministic, developers may accidentally commit real keys, and cross-language test scenarios become difficult to coordinate. + +## Decision + +1. MAY: Additional fake keys beyond the initial set MAY be added following the sequential naming convention (_FAKE_RSA_KEY_5, _FAKE_RSA_KEY_6, etc.) as test scenarios require + +## Policy Block + +- MAY Additional fake keys beyond the initial set MAY be added following the sequential naming convention (_FAKE_RSA_KEY_5, _FAKE_RSA_KEY_6, etc.) as test scenarios require + +In scope: +- All test code in the Rust SDK module (util/RustSdk/rust/src/) +- Test fixtures for C# interop code consuming Rust cryptographic functions via csbindgen-generated bindings +- Unit tests, integration tests, and protocol validation tests requiring RSA key pairs +- Build-time test execution in build.rs or test harnesses + +Out of scope: +- Production cryptographic operations using real key material +- Key generation, storage, or management in production environments +- Non-RSA cryptographic algorithms (AES, ECDSA, etc.) unless similar fake fixture patterns are explicitly adopted +- External test frameworks or test data not directly related to the Rust SDK FFI boundary + +Exceptions: +- EXC-001: Performance benchmarking requires real key generation timing measurements + +## Rationale + +- The evidence shows 5 distinct fake RSA keys embedded in rsa_keys.rs, each containing full 2048-bit PEM-encoded private keys, demonstrating a deliberate strategy for deterministic cryptographic testing +- The csbindgen build configuration in build.rs exposes Rust cipher operations to C# via FFI, requiring test fixtures that work identically across both language runtimes without external dependencies +- Embedding fake keys as const string literals ensures they are compiled into the binary, eliminating file I/O, path resolution, and environment-specific test failures +- The pattern supports testing complex scenarios like key rotation (multiple keys), multi-party protocols (distinct key pairs), and edge cases (malformed keys) without generating keys at test runtime + +## Consequences + +Positive: +- Tests become fully deterministic and reproducible across all environments, CI systems, and developer machines +- No risk of accidentally committing real private keys to version control since all keys are explicitly marked as fake +- Cross-language FFI tests can use identical key material in both Rust and C# test suites, ensuring protocol compatibility +- Test execution speed improves by eliminating runtime key generation overhead + +Negative: +- Embedded PEM-encoded keys significantly increase source file size (each 2048-bit key is ~1600 characters) +- Developers must manually ensure fake keys are never accidentally used in production code paths +- Key rotation testing is limited to the pre-generated set of fake keys unless additional keys are added to source +- The pattern does not test key generation logic itself, only operations using existing key material + +## Alternatives + +- Generate RSA keys dynamically at test runtime using a cryptographic library with a fixed seed (rejected) + Rejected because: Runtime key generation adds 50-200ms overhead per test, complicates FFI test coordination between Rust and C#, and introduces dependency on key generation library availability in test environments + When valid: Valid for performance benchmarking tests that specifically measure key generation speed +- Load fake RSA keys from external test fixture files (e.g., test_data/fake_key_0.pem) (rejected) + Rejected because: Requires file I/O, path resolution logic, and coordination of test data directories across Rust and C# test runners, increasing test fragility and environment-specific failures + When valid: Valid for integration tests that specifically test key loading from filesystem as part of the API contract +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Insufficient for testing multi-party protocols, key rotation scenarios, and edge cases where distinct key pairs are required to validate protocol correctness + When valid: Valid for simple unit tests of single-key operations like sign/verify where key identity does not matter + +## Risks + +- Developers may accidentally copy fake key constants into production code, creating a critical security vulnerability + Mitigation: Implement static analysis rules to detect _FAKE_RSA_KEY_ pattern usage outside test modules; require code review for any cryptographic code changes; add CI checks that fail if fake key patterns appear in production binaries + Owner: Security team and SDK maintainers +- Embedded fake keys increase source file size and may trigger code review tools or diff viewers to truncate or skip large files + Mitigation: Document the pattern in CONTRIBUTING.md; configure diff tools to handle large const string literals; consider extracting keys to a dedicated test_fixtures.rs module if size becomes problematic + Owner: SDK maintainers +- The fake keys do not test key generation, validation, or parsing logic, potentially missing bugs in those code paths + Mitigation: Maintain separate test suites for key generation and parsing that use dynamic key creation; document that fake keys are for protocol testing only, not key lifecycle testing + Owner: QA and SDK maintainers + +## Implementation Notes + +- Place fake RSA keys in a dedicated module (e.g., src/test_fixtures/rsa_keys.rs) with clear documentation that keys are for testing only +- Use the naming convention _FAKE_RSA_KEY_N with zero-indexed sequential numbering; document the purpose of each key if they represent specific test scenarios (e.g., _FAKE_RSA_KEY_EXPIRED for expiration testing) +- In C# test code consuming the Rust SDK via csbindgen, reference the same fake keys by copying them to a C# test fixture class or by calling Rust test helper functions that return the fake keys +- Add a comment header above each fake key block explaining it is a test fixture and must never be used in production + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ --include='*.rs' | grep -v 'test' | grep -v 'rsa_keys.rs' || echo 'No fake keys in production code' +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -q 'test result: ok' && echo 'RSA key tests pass' +- grep -c 'BEGIN PRIVATE KEY' util/RustSdk/rust/src/rsa_keys.rs | awk '$1 >= 5 {print "Found " $1 " fake keys (minimum 5 required)"}' + +Accept when: +- All test code using RSA operations references _FAKE_RSA_KEY_N constants and no fake key patterns appear in production source files +- At least 5 distinct fake RSA keys are available in the test fixtures module with sequential naming +- All tests exercising FFI-exposed cryptographic functions pass using the fake keys, and C# interop tests can successfully use the same key material + +## Enforcement + +- Verified by: CI pipeline static analysis checks for _FAKE_RSA_KEY_ pattern usage outside test modules +- Verified by: Code review checklist item requiring verification that cryptographic tests use standardized fake keys +- Verified by: Automated grep-based verification in pre-commit hooks that fail if fake key patterns appear in non-test files +- Violation handling: CI build fails if static analysis detects fake key usage in production code paths +- Violation handling: Code review blocks merge if cryptographic tests do not use standardized fake keys or if new fake keys do not follow naming convention +- Violation handling: Security team notification triggered for any violation detected in production branches +- Exception process: Developer opens GitHub issue documenting why an exception is needed (e.g., performance benchmarking requires real key generation) +- Exception process: Security team lead reviews and approves exception with documented justification +- Exception process: Exception is recorded in ADR amendments section with approval date, approver, and expiration date if temporary \ No newline at end of file diff --git a/docs/adr/c74440d5-44bb-41b7-9a51-afde8974ce39-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-additional-cryptographic-key.md b/docs/adr/c74440d5-44bb-41b7-9a51-afde8974ce39-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-additional-cryptographic-key.md new file mode 100644 index 000000000000..4b82d1b10ef7 --- /dev/null +++ b/docs/adr/c74440d5-44bb-41b7-9a51-afde8974ce39-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-additional-cryptographic-key.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Additional Cryptographic Key + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. MAY: Additional cryptographic key generation functions MAY be added following the established FFI-safe pattern with paired allocation/deallocation + +## Policy Block + +- MAY Additional cryptographic key generation functions MAY be added following the established FFI-safe pattern with paired allocation/deallocation + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/c775e1b6-3ca1-4da9-88d0-761fad4b473e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-services-processing-notifications.md b/docs/adr/c775e1b6-3ca1-4da9-88d0-761fad4b473e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-services-processing-notifications.md new file mode 100644 index 000000000000..79f0df74fe29 --- /dev/null +++ b/docs/adr/c775e1b6-3ca1-4da9-88d0-761fad4b473e-enforce-warning-level-logging-for-invalid-notification-states-in-push-services-services-processing-notifications.md @@ -0,0 +1,116 @@ +# Enforce Warning-Level Logging for Invalid Notification States in Push Services: Services Processing Notifications + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The push notification service (IPushNotificationService) processes notifications from multiple domain entities including AdminConsole, Auth, and NotificationCenter modules within the Bit.Core namespace +- Invalid notification states (invalid notification ID and invalid notification status ID) are encountered during runtime processing and require observable quality gates +- The codebase uses structured logging with ILogger to record warning-level events when validation failures occur during push notification processing +- A pragma warning disable directive (B) is present, indicating intentional suppression of specific compiler or analyzer warnings in this quality-critical path + +## Problem Statement + +Push notification services must detect and record invalid notification states (malformed IDs or invalid status values) at runtime to enable operational visibility, debugging, and quality assurance, while balancing the need to suppress specific static analysis warnings that may conflict with the chosen logging strategy. + +## Decision + +1. MUST: Services processing notifications from multiple domain entities (AdminConsole, Auth, NotificationCenter) MUST apply consistent validation logging patterns across all entity types + +## Policy Block + +- MUST Services processing notifications from multiple domain entities (AdminConsole, Auth, NotificationCenter) MUST apply consistent validation logging patterns across all entity types + +In scope: +- All implementations of IPushNotificationService interface +- Push notification processing logic handling Bit.Core.NotificationCenter.Entities +- Validation logic for notification IDs and status IDs +- Runtime quality gates for notification state verification + +Out of scope: +- Logging for successful notification processing (use Info or Debug levels) +- Error-level logging for system failures or exceptions +- Validation logic in non-push notification contexts +- Static analysis warning suppression for non-quality-gate purposes + +Exceptions: +- EXC-001: High-frequency notification processing paths where warning-level logging would create excessive log volume + +## Rationale + +- The evidence shows consistent use of ILogger.LogWarning with structured parameters for two distinct invalid notification scenarios, establishing a quality gate pattern for runtime validation +- Push notifications cross multiple domain boundaries (AdminConsole, Auth, NotificationCenter entities), requiring observable validation points to trace failures across module boundaries +- Warning-level logging provides operational visibility without triggering error alerting, appropriate for validation failures that may be recoverable or expected in certain edge cases +- The presence of pragma warning disable B indicates intentional acceptance of static analysis warnings in favor of the runtime observability pattern + +## Consequences + +Positive: +- Operational teams gain visibility into invalid notification states without manual debugging or code instrumentation +- Structured logging with notification IDs enables correlation of validation failures with specific notification instances across distributed logs +- Consistent warning-level logging establishes a quality gate that can be monitored, alerted on, and analyzed for trends +- Cross-module validation failures become observable at the push service boundary, simplifying root cause analysis + +Negative: +- Warning-level logs may accumulate in high-volume notification scenarios, increasing log storage costs and noise +- Suppression of static analysis warnings (pragma disable) reduces compile-time safety checks and may mask related code quality issues +- Developers must maintain discipline to use structured logging templates rather than simpler string concatenation +- The pattern creates a dependency on logging infrastructure availability for quality gate observability + +## Alternatives + +- Use exception throwing for invalid notification states instead of warning-level logging (rejected) + Rejected because: Exceptions would disrupt notification processing flow and trigger error-level alerting for potentially recoverable validation failures, creating operational noise + When valid: When invalid notification states represent unrecoverable errors that should halt processing +- Implement metrics-based counters for invalid notifications without detailed logging (rejected) + Rejected because: Metrics alone lack the contextual detail (specific notification IDs) needed for debugging individual validation failures + When valid: As a complementary approach for high-level trend monitoring alongside detailed logging +- Use Debug-level logging for validation failures (rejected) + Rejected because: Debug-level logs are typically disabled in production, eliminating operational visibility into validation failures + When valid: In development or staging environments where verbose logging is acceptable + +## Risks + +- High-frequency invalid notifications could generate excessive log volume, impacting log infrastructure performance and costs + Mitigation: Implement log sampling or rate limiting for validation warnings if frequency exceeds operational thresholds; monitor log volume metrics + Owner: Platform engineering team +- Pragma warning suppression may mask legitimate code quality issues flagged by static analysis + Mitigation: Document specific warning codes being suppressed; periodically review suppressed warnings to ensure they remain justified + Owner: Code quality team +- Inconsistent application of logging pattern across different notification entity types could create observability gaps + Mitigation: Implement automated verification (linting or testing) to ensure all notification validation paths include structured warning logs + Owner: Engineering team + +## Implementation Notes + +- Use ILogger interface with structured logging templates: logger.LogWarning("Invalid notification id {NotificationId} push notification", notification.Id) +- Apply the pattern consistently across all notification entity types from Bit.Core.AdminConsole.Entities, Bit.Core.Auth.Entities, and Bit.Core.NotificationCenter.Entities +- Document any pragma warning disable directives with comments explaining why the suppression is necessary for the quality gate pattern +- Consider implementing log aggregation queries or dashboards to monitor trends in invalid notification warnings across the platform + +## Continuation Context + + +Verify commands: +- grep -r 'LogWarning.*Invalid notification' src/Core/Platform/Push/ | grep -c 'NotificationId' +- grep -r 'IPushNotificationService' src/ -A 50 | grep -c 'logger.LogWarning' +- find src/Core/Platform/Push/ -name '*.cs' -exec grep -l 'pragma warning disable' {} \; + +Accept when: +- All invalid notification ID scenarios log warning-level events with structured NotificationId parameter +- All invalid notification status ID scenarios log warning-level events with structured NotificationId parameter +- Pragma warning disable directives are documented with comments explaining their relationship to the logging quality gate + +## Enforcement + +- Verified by: Code review checklist requiring structured warning logs for all notification validation failures +- Verified by: Automated grep-based verification in CI pipeline checking for LogWarning patterns in push notification services +- Verified by: Static analysis configuration review to ensure pragma warning suppressions are documented +- Violation handling: Code review rejection if validation failures lack warning-level logging with structured parameters +- Violation handling: CI pipeline warnings if push notification services are modified without corresponding logging verification +- Violation handling: Quarterly audit of pragma warning suppressions to ensure they remain justified and documented +- Exception process: Submit exception request to platform architecture team with performance impact analysis for high-frequency paths +- Exception process: Provide alternative observability mechanism (metrics, sampling strategy) in exception request +- Exception process: Document approved exceptions in service-level README with rationale and compensating controls \ No newline at end of file diff --git a/docs/adr/c7780231-7bef-4325-9208-971b925b454d-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md b/docs/adr/c7780231-7bef-4325-9208-971b925b454d-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md new file mode 100644 index 000000000000..59a0a38f9470 --- /dev/null +++ b/docs/adr/c7780231-7bef-4325-9208-971b925b454d-adopt-test-authentication-scheme-for-integration-testing-test-authentication-handlers.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Handlers + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. MUST: Test authentication handlers MUST return AuthenticateResult.Success() with a ClaimsPrincipal containing test claims + +## Policy Block + +- MUST Test authentication handlers MUST return AuthenticateResult.Success() with a ClaimsPrincipal containing test claims + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/ca94f258-8ca7-4c19-aad5-3ba8b6328c0f-adopt-attribute-based-authorization-model-for-controller-actions-authorization-logic-not.md b/docs/adr/ca94f258-8ca7-4c19-aad5-3ba8b6328c0f-adopt-attribute-based-authorization-model-for-controller-actions-authorization-logic-not.md new file mode 100644 index 000000000000..e748d57de9c7 --- /dev/null +++ b/docs/adr/ca94f258-8ca7-4c19-aad5-3ba8b6328c0f-adopt-attribute-based-authorization-model-for-controller-actions-authorization-logic-not.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Logic Not + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. MUST_NOT: Authorization logic MUST NOT be implemented within action method bodies; all permission checks MUST occur via attribute-based declarative authorization + +## Policy Block + +- MUST_NOT Authorization logic MUST NOT be implemented within action method bodies; all permission checks MUST occur via attribute-based declarative authorization + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/cbc17a37-2cd6-4449-a1ae-9d42f7dc45f5-enforce-authorization-via-policy-based-configuration-in-scim-services-scim-named-policy.md b/docs/adr/cbc17a37-2cd6-4449-a1ae-9d42f7dc45f5-enforce-authorization-via-policy-based-configuration-in-scim-services-scim-named-policy.md new file mode 100644 index 000000000000..3854b5337b50 --- /dev/null +++ b/docs/adr/cbc17a37-2cd6-4449-a1ae-9d42f7dc45f5-enforce-authorization-via-policy-based-configuration-in-scim-services-scim-named-policy.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Scim Named Policy + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. MUST: The 'Scim' named policy MUST be defined with policy.RequireAuthenticatedUser() in production environments + +## Policy Block + +- MUST The 'Scim' named policy MUST be defined with policy.RequireAuthenticatedUser() in production environments + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/cbeaee5b-97cf-4120-9994-da5d9621a7df-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md b/docs/adr/cbeaee5b-97cf-4120-9994-da5d9621a7df-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md new file mode 100644 index 000000000000..9864e07a8266 --- /dev/null +++ b/docs/adr/cbeaee5b-97cf-4120-9994-da5d9621a7df-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. MUST_NOT: Fake RSA key constants MUST NOT be used in production code paths or exposed through public APIs + +## Policy Block + +- MUST_NOT Fake RSA key constants MUST NOT be used in production code paths or exposed through public APIs + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file diff --git a/docs/adr/cdc85dc0-fd41-44d2-a677-7ccca2beebe1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-throw-notfoundexception.md b/docs/adr/cdc85dc0-fd41-44d2-a677-7ccca2beebe1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-throw-notfoundexception.md new file mode 100644 index 000000000000..d08e5471528e --- /dev/null +++ b/docs/adr/cdc85dc0-fd41-44d2-a677-7ccca2beebe1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-throw-notfoundexception.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Throw Notfoundexception + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. MUST: Controllers MUST throw NotFoundException when authorization fails to prevent information disclosure about resource existence + +## Policy Block + +- MUST Controllers MUST throw NotFoundException when authorization fails to prevent information disclosure about resource existence + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/ce6b97e8-0b9b-45b4-bc6f-c2adb5a24a9c-use-structured-logging-with-contextual-parameters-for-external-service-failures-wrap-external-service.md b/docs/adr/ce6b97e8-0b9b-45b4-bc6f-c2adb5a24a9c-use-structured-logging-with-contextual-parameters-for-external-service-failures-wrap-external-service.md new file mode 100644 index 000000000000..521880ced52f --- /dev/null +++ b/docs/adr/ce6b97e8-0b9b-45b4-bc6f-c2adb5a24a9c-use-structured-logging-with-contextual-parameters-for-external-service-failures-wrap-external-service.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Wrap External Service + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. MUST: Wrap external service calls in try-catch blocks when the operation is non-critical to the primary request flow + +## Policy Block + +- MUST Wrap external service calls in try-catch blocks when the operation is non-critical to the primary request flow + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/d009f0b4-3905-4624-80b9-2ca46f364016-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-handlers.md b/docs/adr/d009f0b4-3905-4624-80b9-2ca46f364016-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-handlers.md new file mode 100644 index 000000000000..88e30230323b --- /dev/null +++ b/docs/adr/d009f0b4-3905-4624-80b9-2ca46f364016-adopt-api-key-authentication-scheme-for-scim-service-endpoints-test-authentication-handlers.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Test Authentication Handlers + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. MUST: Test authentication handlers MUST use System.Security.Claims.ClaimsIdentity with organizational admin claims for integration test scenarios + +## Policy Block + +- MUST Test authentication handlers MUST use System.Security.Claims.ClaimsIdentity with organizational admin claims for integration test scenarios + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/d0407e8f-b352-48a5-b1a6-53fdb423ddc1-verify-logger-invocations-in-unit-tests-for-observability-components-unit-tests-verify.md b/docs/adr/d0407e8f-b352-48a5-b1a6-53fdb423ddc1-verify-logger-invocations-in-unit-tests-for-observability-components-unit-tests-verify.md new file mode 100644 index 000000000000..b19c4541d2c2 --- /dev/null +++ b/docs/adr/d0407e8f-b352-48a5-b1a6-53fdb423ddc1-verify-logger-invocations-in-unit-tests-for-observability-components-unit-tests-verify.md @@ -0,0 +1,116 @@ +# Verify Logger Invocations in Unit Tests for Observability Components: Unit Tests Verify + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Unit tests in the codebase verify that logger dependencies are invoked with expected warning messages during error conditions +- The pattern appears in test files for SCIM group operations (PatchGroupCommandTests.cs) and authentication request services (AuthRequestServiceTests.cs) +- Tests use dependency injection providers to retrieve ILogger instances and assert that specific log methods (LogWarning) are called with exact message strings +- This testing approach treats logging as a verifiable behavior rather than an implementation detail, ensuring observability contracts are maintained + +## Problem Statement + +Without explicit verification of logging behavior in unit tests, critical diagnostic messages may be removed or modified during refactoring, degrading operational observability and making production issues harder to diagnose. The codebase needs a consistent approach to ensure logging contracts are tested alongside business logic. + +## Decision + +1. MUST: Unit tests MUST verify that ILogger dependencies are invoked when testing components that perform logging operations + +## Policy Block + +- MUST Unit tests MUST verify that ILogger dependencies are invoked when testing components that perform logging operations + +In scope: +- Unit tests for services and commands that include ILogger dependencies +- Test scenarios covering error conditions, edge cases, or exceptional flows where logging is expected +- Components in the Bit.Core.AdminConsole, Bit.Core.Auth, and similar namespaces that use structured logging + +Out of scope: +- Integration tests where actual logging infrastructure is used rather than mocked +- Performance tests where logger verification overhead is unacceptable +- Tests for components that do not have logging dependencies +- Logging infrastructure implementation tests (e.g., testing the logger itself) + +Exceptions: +- EX-001: The logging behavior is purely diagnostic and not part of any operational contract or alerting logic + +## Rationale + +- The evidence shows 2 test files explicitly verifying ILogger invocations with specific messages, indicating an established pattern for treating logging as testable behavior +- Verifying logger calls ensures that operational observability contracts are maintained across refactoring and code changes +- The pattern uses dependency injection and mocking frameworks (AutoFixture, NSubstitute) already present in the codebase, requiring no additional infrastructure +- Testing logging behavior provides early detection of changes that could impact production diagnostics and incident response + +## Consequences + +Positive: +- Logging contracts become explicit and protected by automated tests, preventing silent degradation of observability +- Developers receive immediate feedback when refactoring removes or changes critical diagnostic messages +- The pattern integrates naturally with existing dependency injection and unit testing infrastructure +- Production incident response is improved through guaranteed availability of expected log messages + +Negative: +- Unit tests become coupled to logging implementation details, potentially increasing test maintenance burden +- Test verbosity increases as logger verification adds additional assertions to each test case +- Refactoring log messages requires updating corresponding test assertions, slowing down minor message improvements +- Over-specification of logging behavior may discourage developers from adding helpful diagnostic logging + +## Alternatives + +- Treat logging as an implementation detail and do not verify logger invocations in unit tests (rejected) + Rejected because: This approach allows critical diagnostic messages to be removed during refactoring without detection, degrading production observability. The evidence shows the codebase has already adopted explicit logger verification. + When valid: For purely diagnostic logging that has no operational significance and is not used for alerting or incident response +- Use integration tests with actual logging infrastructure to verify log output (deferred) + Rejected because: Integration tests provide slower feedback and higher maintenance cost. This approach complements rather than replaces unit-level verification. + When valid: For end-to-end validation of logging configuration, formatting, and sink behavior in staging environments +- Implement custom logging abstractions that separate testable events from log formatting (rejected) + Rejected because: This requires significant infrastructure changes and abstracts away the ILogger pattern already established in the codebase. The current approach works with existing dependencies. + When valid: For greenfield projects or major logging infrastructure redesigns where decoupling events from formatting provides clear architectural benefits + +## Risks + +- Over-specification of log messages in tests creates brittleness, where minor message improvements require widespread test updates + Mitigation: Use ReceivedWithAnyArgs() for non-critical message content and only verify exact messages when they are part of operational contracts or alerting rules + Owner: Engineering team +- Developers may avoid adding helpful logging to avoid increasing test complexity and maintenance burden + Mitigation: Establish clear guidelines on which logging calls require verification (error conditions, security events, operational alerts) versus which are purely diagnostic + Owner: Engineering team and tech leads +- Logger verification may not catch issues with log message formatting, structured logging parameters, or sink configuration + Mitigation: Complement unit-level logger verification with integration tests that validate actual log output in representative environments + Owner: QA and engineering team + +## Implementation Notes + +- Use the sutProvider.GetDependency>() pattern to retrieve logger instances in tests, consistent with existing test infrastructure +- Apply Received(1) or ReceivedWithAnyArgs() from NSubstitute to verify logger method invocations (LogWarning, LogError, etc.) +- Focus logger verification on error paths, security events, and operational alerts where log messages are part of the observable contract +- Document in test comments when logger verification is intentionally omitted for purely diagnostic logging +- Consider extracting logger verification into helper methods when multiple tests verify similar logging patterns + +## Continuation Context + + +Verify commands: +- grep -r 'GetDependency>() calls that retrieve logger instances for verification +- Logger verification uses Received() or ReceivedWithAnyArgs() to assert that log methods were invoked with expected parameters +- Unit tests pass successfully, confirming that logging behavior matches expected contracts + +## Enforcement + +- Verified by: Code review checks for logger verification in unit tests covering error conditions and operational events +- Verified by: CI pipeline runs unit tests that include logger verification assertions +- Verified by: Static analysis or custom linting rules to detect ILogger dependencies without corresponding test verification +- Violation handling: Code review feedback requests addition of logger verification for components with ILogger dependencies +- Violation handling: Pull requests may be blocked if critical error paths lack logging verification +- Violation handling: Retrospective analysis of production incidents identifies missing logging that should have been tested +- Exception process: Developer documents in test comments why logger verification is omitted (e.g., purely diagnostic logging) +- Exception process: Team lead approves exception during code review based on operational significance assessment +- Exception process: Exception is recorded in test file comments for future reference \ No newline at end of file diff --git a/docs/adr/d0768299-875b-48c7-8762-179423ce299e-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-boundary-validation.md b/docs/adr/d0768299-875b-48c7-8762-179423ce299e-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-boundary-validation.md new file mode 100644 index 000000000000..49849cfcfdfd --- /dev/null +++ b/docs/adr/d0768299-875b-48c7-8762-179423ce299e-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-boundary-validation.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Boundary Validation + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. MUST: FFI boundary validation failures MUST return error codes or null pointers to callers rather than panicking + +## Policy Block + +- MUST FFI boundary validation failures MUST return error codes or null pointers to callers rather than panicking + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/d1075a6d-f799-4490-b756-78ce09ef24d0-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-checks-call.md b/docs/adr/d1075a6d-f799-4490-b756-78ce09ef24d0-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-checks-call.md new file mode 100644 index 000000000000..658c3de9297a --- /dev/null +++ b/docs/adr/d1075a6d-f799-4490-b756-78ce09ef24d0-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-authorization-checks-call.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Authorization Checks Call + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. MUST: Authorization checks MUST call AuthorizeAsync with the current User principal, the resource being accessed, and the specific authorization requirement or operation + +## Policy Block + +- MUST Authorization checks MUST call AuthorizeAsync with the current User principal, the resource being accessed, and the specific authorization requirement or operation + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/d13fb5ff-b73e-4677-8d19-7ae186771c89-adopt-test-authentication-scheme-for-integration-testing-test-claims-include.md b/docs/adr/d13fb5ff-b73e-4677-8d19-7ae186771c89-adopt-test-authentication-scheme-for-integration-testing-test-claims-include.md new file mode 100644 index 000000000000..a56d9efaa216 --- /dev/null +++ b/docs/adr/d13fb5ff-b73e-4677-8d19-7ae186771c89-adopt-test-authentication-scheme-for-integration-testing-test-claims-include.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Claims Include + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. SHOULD: Test claims SHOULD include organization identifiers and user context required by authorization policies + +## Policy Block + +- SHOULD Test claims SHOULD include organization identifiers and user context required by authorization policies + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/d17b61a0-9737-4968-b771-1210d7cfb5a1-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-failed-authorization-checks.md b/docs/adr/d17b61a0-9737-4968-b771-1210d7cfb5a1-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-failed-authorization-checks.md new file mode 100644 index 000000000000..58f01b90a371 --- /dev/null +++ b/docs/adr/d17b61a0-9737-4968-b771-1210d7cfb5a1-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-failed-authorization-checks.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Failed Authorization Checks + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. MUST: Failed authorization checks MUST throw NotFoundException rather than UnauthorizedException to prevent information disclosure about entity existence + +## Policy Block + +- MUST Failed authorization checks MUST throw NotFoundException rather than UnauthorizedException to prevent information disclosure about entity existence + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/d2712e9d-1ee5-4a6a-be5b-b080bbbc34e6-use-system-text-json-for-scim-api-data-access-serialization-http-requests-scim.md b/docs/adr/d2712e9d-1ee5-4a6a-be5b-b080bbbc34e6-use-system-text-json-for-scim-api-data-access-serialization-http-requests-scim.md new file mode 100644 index 000000000000..4ea0c2cbad76 --- /dev/null +++ b/docs/adr/d2712e9d-1ee5-4a6a-be5b-b080bbbc34e6-use-system-text-json-for-scim-api-data-access-serialization-http-requests-scim.md @@ -0,0 +1,115 @@ +# Use System.Text.Json for SCIM API Data Access Serialization: Http Requests Scim + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM integration test infrastructure requires serialization of HTTP request and response bodies for API testing +- System.Text.Json is used alongside System.Text.Encodings.Web for JSON serialization in the ScimApplicationFactory test harness +- The test factory implements custom authentication handlers that construct claims-based identities for test scenarios +- Database context SaveChanges operations indicate Entity Framework-based data persistence patterns +- The codebase uses ASP.NET Core authentication and authorization middleware for SCIM endpoint protection + +## Problem Statement + +Integration tests for SCIM API endpoints require consistent serialization of complex domain models (groups, users) to JSON format for HTTP request/response handling, while maintaining compatibility with test authentication infrastructure and database persistence patterns. + +## Decision + +1. SHOULD: HTTP requests to SCIM endpoints SHOULD include System.Net.Mime content type headers + +## Policy Block + +- SHOULD HTTP requests to SCIM endpoints SHOULD include System.Net.Mime content type headers + +In scope: +- SCIM API integration test projects +- ScimApplicationFactory and related test infrastructure +- HTTP request/response serialization for SCIM v2 endpoints +- Entity Framework DatabaseContext operations for SCIM resources + +Out of scope: +- Production SCIM API serialization (may use different configuration) +- Non-SCIM API endpoints +- Unit tests that do not require HTTP serialization +- Client-side SCIM consumer implementations + +## Rationale + +- System.Text.Json is the standard .NET serialization library present in the detected evidence, providing native integration with ASP.NET Core +- The pattern supports async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) observed in the SCIM test infrastructure +- Entity Framework SaveChanges provides transactional data access patterns consistent with SCIM resource lifecycle management +- Claims-based authentication using System.Security.Claims aligns with the test authentication handler implementation detected in the evidence + +## Consequences + +Positive: +- Consistent JSON serialization across all SCIM integration tests using standard .NET libraries +- Native async/await support for HTTP operations improves test execution performance +- Entity Framework integration provides transaction management and change tracking for SCIM resources +- Claims-based test authentication enables flexible simulation of different SCIM client scenarios + +Negative: +- System.Text.Json has different default behavior than Newtonsoft.Json, requiring careful configuration for SCIM schema compliance +- Entity Framework SaveChanges is synchronous and may block async test execution paths +- Test authentication handlers bypass real authentication flows, potentially missing integration issues +- Tight coupling to System.Text.Json makes migration to alternative serializers more difficult + +## Alternatives + +- Use Newtonsoft.Json for SCIM serialization (rejected) + Rejected because: Evidence shows System.Text.Json is already integrated; Newtonsoft.Json would introduce additional dependency without clear benefit for test scenarios + When valid: When SCIM schema compliance requires specific JSON.NET features not available in System.Text.Json +- Use Dapper or raw ADO.NET for data access instead of Entity Framework (rejected) + Rejected because: DatabaseContext.SaveChanges pattern indicates Entity Framework is established; changing would require significant refactoring of test infrastructure + When valid: When performance profiling shows Entity Framework overhead is unacceptable for test execution time +- Use real authentication instead of TestAuthHandler (deferred) + Rejected because: Test authentication provides isolation and speed; real authentication adds external dependencies + When valid: When integration tests need to verify actual authentication flows or token validation logic + +## Risks + +- System.Text.Json serialization defaults may not match SCIM v2 schema requirements for property naming and null handling + Mitigation: Configure JsonSerializerOptions explicitly in test factory; validate against SCIM schema compliance tests + Owner: SCIM integration team +- Entity Framework change tracking overhead may slow integration test execution as test suite grows + Mitigation: Monitor test execution time; consider AsNoTracking for read-only test scenarios; profile database operations + Owner: Engineering team +- Test authentication handler divergence from production authentication may hide security issues + Mitigation: Maintain separate end-to-end tests with real authentication; document differences between test and production auth + Owner: Security team + +## Implementation Notes + +- Configure JsonSerializerOptions with PropertyNamingPolicy and DefaultIgnoreCondition appropriate for SCIM schema +- Use GetStringContent helper method to wrap serialized JSON with correct Content-Type headers +- Ensure DatabaseContext is properly scoped per test to avoid state leakage between test cases +- Set User-Agent headers (e.g., 'Okta') in test requests to simulate real SCIM client behavior +- Use QueryString manipulation for SCIM filter/pagination parameters in GET requests + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'DatabaseContext.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'System.Security.Claims' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All SCIM integration test files import System.Text.Json for serialization +- Data persistence operations use DatabaseContext.SaveChanges pattern +- Test authentication handlers construct ClaimsIdentity using System.Security.Claims + +## Enforcement + +- Verified by: Code review of SCIM integration test changes +- Verified by: Static analysis scanning for System.Text.Json usage in test projects +- Verified by: CI pipeline verification that tests use ScimApplicationFactory pattern +- Violation handling: Pull requests introducing alternative serializers in SCIM tests require architecture review +- Violation handling: Tests bypassing DatabaseContext.SaveChanges must document rationale in comments +- Violation handling: Non-compliant test code flagged in code review with request for alignment +- Exception process: Request exception through architecture review board with justification +- Exception process: Document exception in test file comments with ADR reference +- Exception process: Time-bound exceptions require follow-up task to align with standard pattern \ No newline at end of file diff --git a/docs/adr/d376f581-9ece-4f04-a0b9-d56ac4fa12bb-establish-http-client-boundaries-for-external-service-integration-external-http-client.md b/docs/adr/d376f581-9ece-4f04-a0b9-d56ac4fa12bb-establish-http-client-boundaries-for-external-service-integration-external-http-client.md new file mode 100644 index 000000000000..21a5d1f60933 --- /dev/null +++ b/docs/adr/d376f581-9ece-4f04-a0b9-d56ac4fa12bb-establish-http-client-boundaries-for-external-service-integration-external-http-client.md @@ -0,0 +1,121 @@ +# Establish HTTP Client Boundaries for External Service Integration: External Http Client + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires integration with external services and clients through HTTP-based communication channels +- Multiple controllers and services need to make outbound HTTP requests to external systems including SCIM endpoints, pricing services, and third-party identity providers +- The application uses ASP.NET Core framework which provides IHttpClientFactory for managing HTTP client lifecycle and configuration +- External client boundaries are established through dependency injection patterns with services.AddHttpClient() registrations observed in startup configuration +- Test infrastructure requires mock HTTP clients with custom authentication handlers to simulate external service interactions without network dependencies + +## Problem Statement + +Services need a consistent, testable, and maintainable approach to communicate with external HTTP endpoints while managing connection pooling, DNS refresh, handler lifetime, and security concerns such as SSRF protection. Without explicit boundaries, external client dependencies become tightly coupled, difficult to test, and prone to resource exhaustion issues. + +## Decision + +1. MUST: External HTTP client instances MUST be created through IHttpClientFactory using services.AddHttpClient() registration rather than direct HttpClient instantiation + +## Policy Block + +- MUST External HTTP client instances MUST be created through IHttpClientFactory using services.AddHttpClient() registration rather than direct HttpClient instantiation + +In scope: +- All outbound HTTP requests to external services, APIs, and third-party integrations +- SCIM endpoint integrations for user and group provisioning +- Pricing service client communications +- Identity provider and SSO configuration endpoints +- Test infrastructure HTTP client mocking and simulation + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database connections and repository layer data access +- Message queue or event bus communications +- File system or blob storage access +- In-process method calls or local service invocations + +Exceptions: +- EXC-001: Legacy code paths that have not yet been migrated to IHttpClientFactory pattern +- EXC-002: Performance-critical paths where HttpClient lifecycle is explicitly managed and validated through load testing + +## Rationale + +- IHttpClientFactory manages HttpClient lifecycle correctly, preventing socket exhaustion and DNS staleness issues that occur with direct instantiation +- Named clients enable configuration isolation and handler pipeline customization per external service, improving maintainability and testability +- SSRF protection handlers prevent security vulnerabilities when processing user-supplied URLs or redirects +- The pattern observed across 3 files with 79.23% confidence shows consistent adoption in both production code (Startup.cs, OrganizationUsersController.cs) and test infrastructure (ScimApplicationFactory.cs) + +## Consequences + +Positive: +- Proper HTTP client lifecycle management prevents socket exhaustion and improves application stability under load +- Named clients with handler pipelines enable consistent security controls (SSRF protection) and observability (logging, metrics) across all external integrations +- Dependency injection of IHttpClientFactory improves testability by enabling mock HTTP responses in test environments +- Centralized client registration in startup configuration provides clear visibility into all external service dependencies + +Negative: +- Additional configuration complexity in startup code for each named client registration +- Developers must understand IHttpClientFactory patterns rather than simpler direct HttpClient usage +- Named client proliferation can occur if not properly managed, leading to configuration sprawl +- Test infrastructure requires additional setup for custom authentication handlers and mock server configuration + +## Alternatives + +- Direct HttpClient instantiation with manual lifecycle management (rejected) + Rejected because: Leads to socket exhaustion, DNS staleness, and resource leaks when not disposed correctly. Does not provide handler pipeline extensibility for cross-cutting concerns like SSRF protection. + When valid: Never recommended for production code; only acceptable in throwaway scripts or prototypes +- Single shared HttpClient instance across the application (rejected) + Rejected because: Cannot support different configurations, timeouts, or handler pipelines per external service. Makes testing difficult as all services share the same client state. + When valid: Only when all external services have identical requirements and no service-specific configuration is needed +- Typed clients with IHttpClientFactory (deferred) + Rejected because: Not rejected; represents an evolution of the current pattern. Typed clients provide stronger typing and encapsulation but require more upfront design. + When valid: When external service integration complexity justifies dedicated client classes with strongly-typed methods + +## Risks + +- Named client configuration drift where different parts of the codebase register clients with inconsistent security or timeout settings + Mitigation: Establish naming conventions and configuration templates for common external service types. Implement startup validation to detect duplicate or misconfigured client registrations. + Owner: Platform engineering team +- Test environment HTTP client mocks may not accurately reflect production behavior, leading to integration failures + Mitigation: Implement contract testing or record/replay mechanisms to validate mock responses against actual external service behavior. Include integration tests against staging environments. + Owner: QA and development teams +- SSRF protection may be inadvertently omitted when adding new external client integrations + Mitigation: Create code review checklist requiring SSRF protection verification for all AddHttpClient registrations. Consider custom analyzers to detect missing protection handlers. + Owner: Security and engineering teams + +## Implementation Notes + +- Register all HTTP clients in Startup.cs ConfigureServices method using services.AddHttpClient() or services.AddHttpClient(name) for named clients +- For clients that process user-supplied URLs, chain .AddSsrfProtection() to the registration: services.AddHttpClient(name).AddSsrfProtection() +- In test projects, configure custom authentication handlers by calling services.AddAuthentication(scheme).AddScheme() before HTTP client registration +- Inject IHttpClientFactory into services and call CreateClient() or CreateClient(name) to obtain configured instances rather than constructing HttpClient directly + +## Continuation Context + + +Verify commands: +- grep -r 'new HttpClient()' --include='*.cs' --exclude-dir='{bin,obj}' . | grep -v '// legacy' || echo 'No direct HttpClient instantiation found' +- grep -r 'AddHttpClient' --include='*.cs' src/ | grep -c 'AddSsrfProtection' && echo 'SSRF protection handlers detected' +- grep -r 'IHttpClientFactory' --include='*.cs' src/ | wc -l && echo 'IHttpClientFactory injection points found' + +Accept when: +- All production code uses IHttpClientFactory for HTTP client creation with no direct 'new HttpClient()' instantiations outside documented legacy exceptions +- All HTTP clients that accept user-supplied URLs include AddSsrfProtection() in their registration pipeline +- Test infrastructure successfully uses custom authentication handlers without requiring network access to external services + +## Enforcement + +- Verified by: Code review checklist verification for all pull requests adding external service integrations +- Verified by: Static analysis or custom Roslyn analyzers detecting direct HttpClient instantiation patterns +- Verified by: Integration test suite validation that external client boundaries are properly mocked in test environments +- Violation handling: Pull requests with direct HttpClient instantiation are blocked until refactored to use IHttpClientFactory +- Violation handling: Missing SSRF protection on user-facing endpoints triggers security review and blocks deployment +- Violation handling: Violations discovered in production code are tracked as P1 technical debt items with mandatory remediation timeline +- Exception process: Developer submits exception request with justification and evidence (performance tests, migration plan, or architectural constraints) +- Exception process: Technical lead or architecture review board evaluates request against policy exception criteria +- Exception process: Approved exceptions are documented in code comments with tracking ticket reference and expiration date +- Exception process: Exception registry is reviewed quarterly to ensure temporary exceptions are resolved or renewed with updated justification \ No newline at end of file diff --git a/docs/adr/d47f7772-dcb8-4c92-a949-c0a8fef043ad-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md b/docs/adr/d47f7772-dcb8-4c92-a949-c0a8fef043ad-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md new file mode 100644 index 000000000000..419a69a59163 --- /dev/null +++ b/docs/adr/d47f7772-dcb8-4c92-a949-c0a8fef043ad-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-string-validation.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi String Validation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. SHOULD: FFI string validation SHOULD occur before any cryptographic operations or sensitive data processing + +## Policy Block + +- SHOULD FFI string validation SHOULD occur before any cryptographic operations or sensitive data processing + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/d4fedf70-1502-4676-a146-a2f18eee1340-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-return.md b/docs/adr/d4fedf70-1502-4676-a146-a2f18eee1340-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-return.md new file mode 100644 index 000000000000..3fbc3f611898 --- /dev/null +++ b/docs/adr/d4fedf70-1502-4676-a146-a2f18eee1340-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-return.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Return + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. MAY: FFI functions MAY return error codes or null pointers to indicate validation failures rather than panicking + +## Policy Block + +- MAY FFI functions MAY return error codes or null pointers to indicate validation failures rather than panicking + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/d5ace3d3-7f05-4d88-bfe2-cc82cf13a7e3-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-use.md b/docs/adr/d5ace3d3-7f05-4d88-bfe2-cc82cf13a7e3-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-use.md new file mode 100644 index 000000000000..d363a7cd57d2 --- /dev/null +++ b/docs/adr/d5ace3d3-7f05-4d88-bfe2-cc82cf13a7e3-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-integration-tests-use.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Integration Tests Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. SHOULD: Integration tests SHOULD use FormUrlEncodedContent with explicit Dictionary for token request parameters including scope, client_id, grant_type, and device information + +## Policy Block + +- SHOULD Integration tests SHOULD use FormUrlEncodedContent with explicit Dictionary for token request parameters including scope, client_id, grant_type, and device information + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/d6b99429-7694-4bb1-831c-eeb84b33654c-enforce-authorization-service-pattern-for-access-control-decisions-bulk-operations-verify.md b/docs/adr/d6b99429-7694-4bb1-831c-eeb84b33654c-enforce-authorization-service-pattern-for-access-control-decisions-bulk-operations-verify.md new file mode 100644 index 000000000000..23a127c8eb7b --- /dev/null +++ b/docs/adr/d6b99429-7694-4bb1-831c-eeb84b33654c-enforce-authorization-service-pattern-for-access-control-decisions-bulk-operations-verify.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Bulk Operations Verify + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. MUST: Bulk operations MUST verify authorization for each affected resource using BulkCollectionOperations or equivalent authorization operations + +## Policy Block + +- MUST Bulk operations MUST verify authorization for each affected resource using BulkCollectionOperations or equivalent authorization operations + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/d7303975-2017-4fe8-90bb-4a566464eef6-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-cover-both.md b/docs/adr/d7303975-2017-4fe8-90bb-4a566464eef6-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-cover-both.md new file mode 100644 index 000000000000..758c1322b32d --- /dev/null +++ b/docs/adr/d7303975-2017-4fe8-90bb-4a566464eef6-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-cover-both.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Cover Both + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. SHOULD: Tests SHOULD cover both empty state scenarios (NoCurrentGrantedPolicies, NoCurrentAccessPolicies) and change detection scenarios (CurrentGrantedPolicies, CurrentAccessPolicies) to validate conditional branching + +## Policy Block + +- SHOULD Tests SHOULD cover both empty state scenarios (NoCurrentGrantedPolicies, NoCurrentAccessPolicies) and change detection scenarios (CurrentGrantedPolicies, CurrentAccessPolicies) to validate conditional branching + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/d74bb1a6-73ee-4c6e-bdbb-ad4d548547b1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-inject-iauthorizationservice.md b/docs/adr/d74bb1a6-73ee-4c6e-bdbb-ad4d548547b1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-inject-iauthorizationservice.md new file mode 100644 index 000000000000..e8d674dceb52 --- /dev/null +++ b/docs/adr/d74bb1a6-73ee-4c6e-bdbb-ad4d548547b1-enforce-authorization-at-controller-endpoints-using-iauthorizationservice-controllers-inject-iauthorizationservice.md @@ -0,0 +1,126 @@ +# Enforce Authorization at Controller Endpoints Using IAuthorizationService: Controllers Inject Iauthorizationservice + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controllers requiring authorization enforcement in ASP.NET Core application frameworks. + +## Context + +- The application uses Microsoft.AspNetCore.Authorization framework to protect API endpoints from unauthorized access +- Controllers require fine-grained authorization decisions beyond simple authentication, including resource-based authorization checks +- Multiple authorization requirements exist (ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement) that must be evaluated at runtime +- Authorization decisions depend on both user identity (ClaimsPrincipal) and resource context (organization membership, collection access) +- Test infrastructure requires configurable authorization policies to enable integration testing without production authentication dependencies + +## Problem Statement + +API controllers must enforce authorization consistently across endpoints while supporting complex, resource-dependent access control rules that cannot be expressed through declarative attributes alone. The system needs a mechanism to evaluate authorization requirements programmatically, handle authorization failures uniformly, and maintain testability through policy configuration. + +## Decision + +1. MUST: Controllers MUST inject IAuthorizationService through constructor dependency injection + +## Policy Block + +- MUST Controllers MUST inject IAuthorizationService through constructor dependency injection + +In scope: +- All ASP.NET Core MVC and API controllers requiring authorization +- Authorization handlers implementing IAuthorizationHandler or AuthorizationHandler +- Service configuration in Startup or Program.cs registering authorization policies +- Integration test factories configuring test authentication and authorization schemes + +Out of scope: +- Authentication mechanisms (handled by authentication middleware) +- Authorization decisions within domain services or business logic layers +- Client-side authorization UI rendering decisions +- Authorization for non-HTTP entry points (background jobs, message handlers) + +Exceptions: +- EX-001: Public endpoints that require no authorization +- EX-002: Test environments using simplified authorization policies + +## Rationale + +- IAuthorizationService provides a centralized, testable abstraction for authorization decisions that separates policy definition from enforcement +- Resource-based authorization requires runtime evaluation of user permissions against specific entities (collections, organization users) that cannot be determined at compile time +- Throwing NotFoundException on authorization failure prevents attackers from enumerating resources by distinguishing between 'does not exist' and 'access denied' responses +- Constructor injection of IAuthorizationService enables unit testing with mock authorization services and integration testing with configured test policies + +## Consequences + +Positive: +- Consistent authorization enforcement across all controller endpoints reduces security vulnerabilities from missed checks +- Centralized authorization logic in handlers enables reuse across multiple controllers and endpoints +- Testability improves through dependency injection and configurable policies in test environments +- Clear separation between authentication (who you are) and authorization (what you can do) simplifies security reasoning + +Negative: +- Additional boilerplate code required in controllers to call AuthorizeAsync and handle authorization results +- Performance overhead from authorization service invocation on every protected endpoint +- Complexity increases when combining declarative attributes with imperative authorization checks +- Debugging authorization failures requires understanding both policy configuration and handler implementation + +## Alternatives + +- Use only declarative [Authorize] attributes with policy names (rejected) + Rejected because: Declarative attributes cannot access resource context needed for resource-based authorization decisions (e.g., checking collection access permissions) + When valid: Simple role-based or claims-based authorization without resource-specific rules +- Implement custom authorization filters or middleware (rejected) + Rejected because: Custom filters duplicate framework functionality and reduce maintainability; IAuthorizationService already provides extensible authorization infrastructure + When valid: Cross-cutting authorization concerns that apply uniformly across all endpoints without resource context +- Perform authorization checks in domain services or repositories (rejected) + Rejected because: Violates separation of concerns by mixing authorization with business logic; makes authorization harder to test and audit + When valid: Domain-level invariants that must be enforced regardless of entry point (not HTTP-specific authorization) + +## Risks + +- Developers may forget to add authorization checks to new endpoints, creating security vulnerabilities + Mitigation: Implement automated security testing that verifies all endpoints have authorization checks; use code review checklists; consider default-deny authorization policies + Owner: Security team and engineering team +- Inconsistent error handling when authorization fails may leak information about resource existence + Mitigation: Establish standard pattern of throwing NotFoundException on authorization failure; document in security guidelines; implement automated checks for authorization error handling patterns + Owner: Security team +- Test authorization policies may accidentally be deployed to production environments + Mitigation: Isolate test authentication handlers to test projects; use environment-specific configuration; implement deployment validation checks + Owner: DevOps team and engineering team + +## Implementation Notes + +- Register IAuthorizationService in DI container using services.AddAuthorization() in application startup +- Define custom authorization requirements by implementing IAuthorizationRequirement and corresponding handlers implementing AuthorizationHandler +- In controllers, inject IAuthorizationService and call await _authorizationService.AuthorizeAsync(User, resource, requirement) before accessing protected resources +- Handle authorization failures by checking AuthorizationResult.Succeeded and throwing NotFoundException to prevent information disclosure +- For test environments, configure policies using config.AddPolicy with RequireAssertion for controlled test scenarios + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r 'AddAuthorization' --include='*.cs' src/ test/ | grep -v '//' +- grep -r 'class.*AuthorizationHandler' --include='*.cs' src/ | wc -l + +Accept when: +- All controller files containing protected endpoints inject IAuthorizationService through constructor +- All resource-based authorization decisions call AuthorizeAsync before granting access +- Authorization policies are registered in service configuration with AddAuthorization +- Test projects configure authorization policies separately from production configuration + +## Enforcement + +- Verified by: Automated security testing scanning for endpoints without authorization checks +- Verified by: Code review checklist requiring verification of authorization enforcement +- Verified by: Static analysis tools detecting IAuthorizationService usage patterns +- Verified by: Integration tests validating authorization behavior for each protected endpoint +- Violation handling: Security vulnerabilities from missing authorization checks are treated as critical defects requiring immediate remediation +- Violation handling: Pull requests without proper authorization checks are blocked until corrected +- Violation handling: Periodic security audits identify and track authorization enforcement gaps +- Exception process: Exceptions for public endpoints must be explicitly documented with [AllowAnonymous] attribute and security team approval +- Exception process: Alternative authorization mechanisms require security architecture review and documentation +- Exception process: All exceptions must be recorded in security documentation with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/d7c80df6-2821-40b1-896c-773d22cd3543-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-build-scripts-declare.md b/docs/adr/d7c80df6-2821-40b1-896c-773d22cd3543-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-build-scripts-declare.md new file mode 100644 index 000000000000..c39ab323bd8c --- /dev/null +++ b/docs/adr/d7c80df6-2821-40b1-896c-773d22cd3543-standardize-c-ffi-bindings-generation-for-rust-sdk-public-apis-build-scripts-declare.md @@ -0,0 +1,121 @@ +# Standardize C# FFI Bindings Generation for Rust SDK Public APIs: Build Scripts Declare + +Status: proposed +Date: 2025-01-10 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust SDK modules that expose public APIs to C# consumers through FFI bindings. + +## Context + +- The Rust SDK requires interoperability with C# codebases, necessitating a Foreign Function Interface (FFI) boundary between Rust native code and managed .NET environments. +- The csbindgen library is used in the build process to automatically generate C# binding code from Rust extern functions, reducing manual marshalling code and synchronization errors. +- Test fixtures including fake RSA private keys are embedded in the Rust codebase to support testing of cryptographic operations without requiring real key material. +- The SDK exposes cryptographic functionality (cipher operations, RSA key handling) that must maintain consistent interfaces across language boundaries. +- Build-time code generation ensures that API contracts between Rust and C# remain synchronized as the Rust implementation evolves. + +## Problem Statement + +Cross-language API boundaries between Rust and C# require explicit marshalling, type mapping, and interface synchronization. Manual maintenance of FFI bindings is error-prone and creates drift between Rust implementations and C# consumers. Without automated binding generation, changes to Rust function signatures require coordinated manual updates to C# wrapper code, increasing maintenance burden and risk of runtime failures at the FFI boundary. + +## Decision + +1. MUST: Build scripts MUST declare all Rust source files containing extern functions as inputs to the binding generator using input_extern_file. + +## Policy Block + +- MUST Build scripts MUST declare all Rust source files containing extern functions as inputs to the binding generator using input_extern_file. + +In scope: +- All Rust modules in util/RustSdk that expose extern functions for C# consumption +- Build scripts (build.rs) responsible for generating language bindings +- Test fixtures and mock data used for cryptographic operation testing +- Public API surface exposed through FFI to managed C# code + +Out of scope: +- Internal Rust-only modules with no C# interop requirements +- C# code that does not interact with Rust native libraries +- Production cryptographic key management and storage +- Runtime key generation or key derivation logic + +Exceptions: +- EXC-001: Prototype or experimental Rust modules may defer binding generation until API stability is confirmed + +## Rationale + +- The evidence shows csbindgen is already integrated in build.rs, generating bindings from lib.rs and cipher.rs, establishing a working pattern for automated FFI boundary management. +- Five distinct fake RSA key constants in rsa_keys.rs demonstrate a systematic approach to providing test fixtures for cryptographic operations without embedding real key material. +- Automated binding generation reduces the risk of type mismatches and calling convention errors that commonly occur at FFI boundaries between Rust and managed languages. +- The pattern supports maintainability by ensuring that Rust API changes automatically propagate to C# consumers through regenerated bindings at build time. + +## Consequences + +Positive: +- Eliminates manual synchronization of FFI interfaces between Rust and C#, reducing maintenance overhead and human error. +- Provides type-safe C# wrappers automatically derived from Rust function signatures, catching interface mismatches at compile time. +- Enables rapid iteration on Rust SDK functionality with confidence that C# consumers receive updated bindings automatically. +- Establishes clear separation between test fixtures (fake keys) and production cryptographic material through naming conventions. + +Negative: +- Introduces build-time dependency on csbindgen, requiring Rust toolchain and csbindgen crate availability in build environments. +- Generated C# code may be less idiomatic than hand-written wrappers, potentially requiring additional wrapper layers for ergonomic C# APIs. +- Changes to Rust function signatures trigger regeneration of C# bindings, which may break downstream C# code if not managed with versioning. +- Test fixtures embedded in source code increase repository size and may be mistaken for production code without clear naming conventions. + +## Alternatives + +- Manually write and maintain C# P/Invoke declarations for all Rust extern functions (rejected) + Rejected because: Manual maintenance creates synchronization burden and high risk of runtime failures due to signature mismatches between Rust and C# declarations + When valid: Only viable for very small, stable APIs with infrequent changes +- Use a different FFI binding generator such as cbindgen (C bindings) with additional C-to-C# layer (rejected) + Rejected because: Adds an extra layer of indirection (Rust -> C -> C#) and does not directly generate C# code, increasing complexity + When valid: When targeting multiple managed languages beyond C# or when C ABI compatibility is required +- Expose Rust functionality through a REST API or gRPC service instead of FFI (rejected) + Rejected because: Introduces network latency and serialization overhead unacceptable for cryptographic operations requiring low-latency, in-process execution + When valid: When Rust and C# components run in separate processes or services with relaxed latency requirements + +## Risks + +- Generated C# bindings may expose unsafe or low-level APIs that C# consumers misuse, leading to memory safety violations or undefined behavior + Mitigation: Provide high-level C# wrapper classes that encapsulate unsafe FFI calls and enforce safe usage patterns; document unsafe APIs clearly + Owner: SDK engineering team +- Fake RSA key constants may be accidentally referenced in production code paths, compromising security + Mitigation: Use compile-time feature flags or conditional compilation to exclude test fixtures from release builds; implement static analysis checks to detect test constant usage in production modules + Owner: Security and SDK engineering teams +- Breaking changes to Rust function signatures will break C# consumers without versioning strategy + Mitigation: Implement semantic versioning for the SDK; maintain compatibility shims for deprecated APIs; provide migration guides for breaking changes + Owner: SDK engineering team + +## Implementation Notes + +- Ensure build.rs is executed as part of the standard Cargo build process; verify that generated C# files (e.g., NativeMethods.g.cs) are included in C# project references. +- Establish naming conventions for test fixtures (e.g., _FAKE_*, _TEST_*, _MOCK_*) and document them in SDK contribution guidelines. +- Configure CI/CD pipelines to verify that generated C# bindings compile successfully against the C# codebase before merging Rust changes. +- Consider wrapping generated low-level bindings in higher-level C# classes that provide idiomatic .NET APIs and handle resource cleanup (IDisposable pattern). + +## Continuation Context + + +Verify commands: +- grep -r 'csbindgen::Builder' util/RustSdk/rust/build.rs +- grep -r '_FAKE_RSA_KEY' util/RustSdk/rust/src/ | grep -c 'const' +- test -f util/RustSdk/NativeMethods.g.cs && echo 'Generated bindings exist' + +Accept when: +- The build.rs script contains csbindgen::Builder configuration with input_extern_file, csharp_dll_name, csharp_namespace, and generate_csharp_file calls +- At least one fake cryptographic key constant is defined with a clear test-only naming convention (e.g., _FAKE_*, _TEST_*) +- Generated C# binding files exist in the expected output location and are included in the C# project structure + +## Enforcement + +- Verified by: Automated CI checks verify that build.rs successfully generates C# bindings and that generated files compile +- Verified by: Code review process checks for proper use of csbindgen configuration and test fixture naming conventions +- Verified by: Static analysis tools scan for usage of test constants (e.g., _FAKE_*) in non-test production code paths +- Violation handling: CI build failures if csbindgen generation fails or generated C# code does not compile +- Violation handling: Code review rejection if FFI functions are added without corresponding build.rs configuration updates +- Violation handling: Security review escalation if test cryptographic material is detected in production code paths +- Exception process: Request exception through engineering lead with documented justification for manual FFI binding maintenance +- Exception process: Prototype or experimental modules may defer binding generation until API stabilization, with tracking issue created +- Exception process: Exception approval requires documented plan for eventual compliance or removal of non-compliant code \ No newline at end of file diff --git a/docs/adr/d7cf8560-2b44-4465-8754-102fecae7236-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-public-ffi-functions.md b/docs/adr/d7cf8560-2b44-4465-8754-102fecae7236-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-public-ffi-functions.md new file mode 100644 index 000000000000..7394e234da6b --- /dev/null +++ b/docs/adr/d7cf8560-2b44-4465-8754-102fecae7236-validate-ffi-input-using-rust-cstr-cstring-for-c-interop-boundaries-public-ffi-functions.md @@ -0,0 +1,116 @@ +# Validate FFI Input Using Rust CStr/CString for C Interop Boundaries: Public Ffi Functions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary for consumption by non-Rust clients +- FFI functions accept raw C string pointers (c_char) and must safely convert them to Rust types while preventing undefined behavior from malformed or malicious input +- The codebase handles sensitive cryptographic material (SymmetricCryptoKey, RSA key pairs via RSA_POOL) requiring strict input validation to prevent security vulnerabilities +- Memory management across the FFI boundary requires explicit handling with free_c_string to prevent leaks when returning strings to C callers +- The std::ffi module (CStr, CString) provides safe abstractions for validating null-terminated C strings before use in Rust code + +## Problem Statement + +FFI boundaries expose Rust cryptographic functions to C callers, creating risk of undefined behavior, memory corruption, or security vulnerabilities if raw C string pointers are used without validation. Unchecked c_char pointers may contain invalid UTF-8, missing null terminators, or malicious payloads that could compromise cryptographic operations or cause crashes. + +## Decision + +1. SHOULD: Public FFI functions (pub extern "C") SHOULD document their null-safety requirements and expected string encoding in comments + +## Policy Block + +- SHOULD Public FFI functions (pub extern "C") SHOULD document their null-safety requirements and expected string encoding in comments + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Key generation functions: generate_user_keys, generate_organization_keys, generate_user_organization_key +- Any FFI function handling cryptographic material (ciphers, RSA keys, symmetric keys) +- Memory management functions like free_c_string + +Out of scope: +- Pure Rust functions with no FFI boundary (internal implementation details) +- FFI functions accepting only primitive types (integers, booleans) with no pointer indirection +- Test code using mocking frameworks where FFI validation is explicitly bypassed + +Exceptions: +- EXC-001: Performance-critical hot paths where input is pre-validated by a trusted caller + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} in lib.rs alongside cryptographic operations, indicating intentional input validation at the FFI boundary +- Public FFI contracts (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) expose sensitive cryptographic functionality requiring defense against malformed input +- CStr provides safe validation of null-terminated C strings, preventing undefined behavior from missing terminators or invalid UTF-8 sequences +- The pattern appears in a single file with 91% confidence, suggesting a localized but critical security control point for the Rust SDK's C interop layer + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating all external input before processing +- Provides clear memory ownership semantics with CString/free_c_string pattern preventing leaks +- Enables safe interop with C/C++ clients while maintaining Rust's memory safety guarantees + +Negative: +- Adds runtime overhead for string validation on every FFI call (null terminator checks, UTF-8 validation) +- Increases code complexity at FFI boundaries with explicit conversion and error handling logic +- Requires C callers to understand and implement proper memory management (calling free_c_string) +- May introduce subtle bugs if validation errors are not properly propagated to C callers + +## Alternatives + +- Use raw pointer dereferencing without CStr/CString validation (rejected) + Rejected because: Exposes cryptographic operations to undefined behavior from malformed input, creating critical security vulnerabilities and violating Rust safety principles + When valid: Never valid for production FFI boundaries handling untrusted input or cryptographic material +- Require C callers to pass length-prefixed strings instead of null-terminated (rejected) + Rejected because: Breaks compatibility with standard C string conventions and increases integration burden for C/C++ clients expecting null-terminated strings + When valid: Valid for new FFI APIs where both sides can coordinate on length-prefixed protocols +- Use higher-level FFI bindings (cbindgen, cxx crate) to auto-generate safe wrappers (deferred) + Rejected because: Not rejected; could complement manual validation but requires tooling changes and may not cover all edge cases in cryptographic context + When valid: Valid for future refactoring to reduce manual FFI boilerplate while maintaining validation guarantees + +## Risks + +- Validation errors at FFI boundary may be silently ignored by C callers if error handling is not properly implemented + Mitigation: Document error return codes clearly, provide example C code demonstrating proper error checking, add integration tests verifying error propagation + Owner: Rust SDK team +- Performance overhead from repeated string validation in high-frequency FFI calls may impact latency-sensitive operations + Mitigation: Profile FFI call overhead, consider caching validated strings where safe, document performance characteristics for callers + Owner: Engineering team +- Memory leaks if C callers fail to call free_c_string on returned strings + Mitigation: Provide clear documentation and examples, consider RAII wrappers for C++ callers, add leak detection in integration tests + Owner: SDK integration team + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe blocks with explicit null pointer checks before dereferencing c_char pointers +- Convert CStr to Rust String or &str using to_str() or to_string_lossy() depending on UTF-8 requirements +- For returning strings, use CString::new() to create owned C strings and into_raw() to transfer ownership, paired with free_c_string using CString::from_raw() +- Add unit tests for FFI functions with malformed inputs: null pointers, missing terminators, invalid UTF-8 sequences, empty strings + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E '(c_char|CStr|CString)' | wc -l +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'echo {}; grep -A 10 "{}" | grep -E "(CStr::from_ptr|CString::new)"' +- cargo test --package bitwarden-rust-sdk --lib -- ffi --nocapture 2>&1 | grep -i 'validation\|null\|invalid' + +Accept when: +- All public FFI functions accepting c_char pointers use CStr::from_ptr() for validation before use +- All FFI functions returning strings use CString and provide corresponding free functions +- Unit tests exist covering null pointer, invalid UTF-8, and missing terminator cases for FFI functions + +## Enforcement + +- Verified by: Code review checklist requiring CStr/CString usage for all new FFI functions +- Verified by: Clippy lints for unsafe FFI patterns (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests validating error handling for malformed FFI inputs +- Violation handling: CI pipeline fails on detection of raw c_char pointer dereferencing without CStr validation +- Violation handling: Security review required for any FFI function handling cryptographic material without input validation +- Violation handling: Post-merge review flags violations for immediate remediation +- Exception process: Submit exception request to security team with performance profiling data and validation contract documentation +- Exception process: Require explicit unsafe block documentation explaining why validation is skipped +- Exception process: Annual review of all approved exceptions to verify continued validity \ No newline at end of file diff --git a/docs/adr/d87126b1-1707-44e1-a967-b3ed03510e7c-adopt-attribute-based-authorization-model-for-controller-actions-authorization-attributes-placed.md b/docs/adr/d87126b1-1707-44e1-a967-b3ed03510e7c-adopt-attribute-based-authorization-model-for-controller-actions-authorization-attributes-placed.md new file mode 100644 index 000000000000..0001c85243e2 --- /dev/null +++ b/docs/adr/d87126b1-1707-44e1-a967-b3ed03510e7c-adopt-attribute-based-authorization-model-for-controller-actions-authorization-attributes-placed.md @@ -0,0 +1,127 @@ +# Adopt Attribute-Based Authorization Model for Controller Actions: Authorization Attributes Placed + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is ACTIVE for all API controller implementations in the AdminConsole and Admin namespaces. Authorization requirements MUST be declared via attributes on controller actions. + +## Context + +- The codebase implements ASP.NET Core controllers requiring fine-grained authorization controls at the action level, with different permissions needed for different operations within the same resource context +- Multiple controller classes (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) demonstrate consistent use of authorization attributes decorating HTTP endpoint methods +- Authorization requirements vary by operation type (GET, POST, PUT, DELETE) and organizational context (provider admin, organization owner, policy management), necessitating declarative permission enforcement +- The pattern appears in 4 files with 78.97% confidence, indicating a standardized approach to authorization model implementation across the API surface +- Controllers use custom authorization requirements (ManageUsersRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) alongside framework-provided [Authorize] attributes + +## Problem Statement + +API controllers expose operations with varying authorization requirements based on organizational roles, resource ownership, and administrative privileges. Without a consistent, declarative authorization model, permission checks would be scattered throughout controller logic, making security policies difficult to audit, test, and maintain. The system requires a mechanism to enforce authorization rules at the controller action boundary before business logic executes. + +## Decision + +1. MUST: Authorization attributes MUST be placed on individual action methods rather than controller classes when different actions require different permissions + +## Policy Block + +- MUST Authorization attributes MUST be placed on individual action methods rather than controller classes when different actions require different permissions + +In scope: +- All ASP.NET Core MVC and Minimal API controllers in Api and Admin projects +- HTTP action methods (GET, POST, PUT, DELETE) that access organizational or user-scoped resources +- Custom authorization requirement implementations extending IAuthorizationRequirement +- Authorization handlers that evaluate requirement satisfaction based on user claims and context + +Out of scope: +- Internal service layer methods (authorization enforced at controller boundary) +- Background jobs and scheduled tasks (use service-level authorization) +- Database-level row security policies +- Client-side authorization UI rendering logic + +Exceptions: +- EX-001: Public endpoints for invite token validation or version checking require anonymous access +- EX-002: Legacy endpoints marked [Obsolete] may use PostDelete pattern with authorization inherited from Delete method + +## Rationale + +- Attribute-based authorization provides compile-time declaration of security requirements, making authorization policies visible in code navigation and enabling static analysis of permission boundaries +- The ASP.NET Core authorization framework executes attribute-declared requirements before action method invocation, ensuring consistent enforcement without developer-implemented guard clauses +- Evidence shows 4 controller files consistently applying this pattern across different authorization contexts (user management, provider administration, policy management), demonstrating architectural standardization +- Custom requirement types (ManageUsersRequirement, ProviderAdminRequirement) enable domain-specific authorization logic while maintaining declarative syntax at the controller level + +## Consequences + +Positive: +- Authorization requirements are self-documenting at the API endpoint level, improving security auditability and onboarding for new developers +- Centralized authorization handler implementations enable consistent permission evaluation logic across all controllers using the same requirement type +- Framework-enforced authorization execution prevents accidental bypass of security checks through developer error +- Strongly-typed requirement classes provide compile-time safety and IDE support for authorization policy references + +Negative: +- Custom authorization requirements require additional infrastructure (handler implementations, dependency injection registration) compared to simple role-based checks +- Complex authorization logic involving multiple conditions may require multiple attributes or composite requirements, potentially reducing readability +- Attribute-based authorization occurs before model binding, limiting access to request body data for authorization decisions without custom model binding integration +- Testing authorization behavior requires integration tests or authorization handler unit tests rather than simple method-level unit tests + +## Alternatives + +- Implement authorization checks as guard clauses within action method bodies using ICurrentContext or authorization services (rejected) + Rejected because: Scatters authorization logic throughout controller code, making security policies difficult to audit and increasing risk of inconsistent or missing checks + When valid: May be appropriate for complex authorization requiring access to deserialized request models, but should be supplemented with attribute-based base checks +- Use policy-based authorization with string-named policies registered in Startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety and IDE navigation support; custom requirement types provide stronger typing and better discoverability + When valid: Acceptable for simple role-based policies that don't require custom handler logic +- Apply authorization filters globally via MVC options with opt-out for public endpoints (rejected) + Rejected because: Reduces visibility of authorization requirements at the action level and makes it unclear which endpoints have specific permission requirements without examining filter configuration + When valid: Useful for base authentication requirements applied at controller class level, as seen with [Authorize("Application")] + +## Risks + +- Developers may forget to apply authorization attributes to new controller actions, creating unauthorized access vulnerabilities + Mitigation: Implement static analysis rules to detect controller actions without authorization attributes; require security review for all [AllowAnonymous] usage; add integration tests verifying authorization enforcement + Owner: Security team and API development team +- Authorization handler implementations may contain bugs or incomplete permission checks, causing incorrect access grants or denials + Mitigation: Require unit tests for all authorization handlers covering positive and negative cases; conduct security-focused code reviews for handler changes; log authorization decisions for audit trails + Owner: Security team +- Complex authorization requirements may lead to attribute proliferation on actions, reducing code readability + Mitigation: Create composite requirement types for common permission combinations; document authorization patterns in architecture guidelines; refactor overly complex requirements into domain-specific types + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirements by implementing IAuthorizationRequirement marker interface and corresponding AuthorizationHandler or AuthorizationHandler implementations +- Register authorization handlers in dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Use [Authorize] syntax for custom requirements as demonstrated in OrganizationInviteLinksController, ProviderOrganizationsController, and PoliciesController +- For actions requiring multiple authorization checks, apply multiple [Authorize] attributes or create composite requirement types that evaluate multiple conditions +- Document authorization requirement semantics in XML comments on requirement classes to aid developers in selecting appropriate attributes + +## Continuation Context + + +Verify commands: +- grep -r "public.*Task.*IResult\|IActionResult" src/Api src/Admin --include="*Controller.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api/AdminConsole/Authorization src/Admin/Authorization -name "*Requirement.cs" -type f | xargs grep -L "IAuthorizationRequirement" +- dotnet test --filter "Category=Authorization" --logger "console;verbosity=detailed" + +Accept when: +- All controller action methods returning IResult or IActionResult have either [Authorize], [Authorize], or [AllowAnonymous] attributes +- All custom requirement classes implement IAuthorizationRequirement and have corresponding registered handler implementations +- Authorization handler unit tests achieve >90% code coverage and include both positive authorization and denial test cases +- Static analysis passes with no violations of authorization attribute requirements on public controller actions + +## Enforcement + +- Verified by: Static analysis rules in CI pipeline detecting controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on new or modified controller actions +- Verified by: Integration tests validating authorization enforcement for each controller endpoint +- Verified by: Security-focused code reviews for all authorization handler implementations and [AllowAnonymous] usage +- Violation handling: CI pipeline fails if static analysis detects controller actions without authorization attributes +- Violation handling: Pull requests blocked until authorization attributes are added or [AllowAnonymous] is justified with security review approval +- Violation handling: Security incidents involving unauthorized access trigger immediate audit of affected controller authorization configuration +- Violation handling: Quarterly security audits review authorization attribute coverage and handler implementation correctness +- Exception process: Developer documents security rationale for [AllowAnonymous] usage in code comments and pull request description +- Exception process: Security team reviews and approves all [AllowAnonymous] usage during pull request review +- Exception process: Exceptions are tracked in security review log with justification and approval timestamp +- Exception process: Annual review of all [AllowAnonymous] endpoints to validate continued necessity \ No newline at end of file diff --git a/docs/adr/da790b60-15b3-4bf4-9937-0fe3f9aadba9-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-controller.md b/docs/adr/da790b60-15b3-4bf4-9937-0fe3f9aadba9-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-controller.md new file mode 100644 index 000000000000..1dbf7c9e2bdf --- /dev/null +++ b/docs/adr/da790b60-15b3-4bf4-9937-0fe3f9aadba9-enforce-organization-scoped-authorization-requirements-for-billing-operations-organization-billing-controller.md @@ -0,0 +1,115 @@ +# Enforce Organization-Scoped Authorization Requirements for Billing Operations: Organization Billing Controller + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bit.Api.Billing namespace contains controllers that expose organization billing operations including subscription management, invoice preview, billing address updates, credit management, and payment method operations +- These billing endpoints operate on Organization entities that are injected via the [InjectOrganization] attribute and bound to controller actions through [BindNever] parameters +- The ManageOrganizationBillingRequirement authorization requirement is consistently applied across billing endpoints to enforce organization-scoped access control +- The authorization model separates billing operations from general administrative operations through dedicated requirements in Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements namespaces +- The pattern appears in PreviewInvoiceController and OrganizationBillingVNextController with 79% confidence across 2 files, indicating a deliberate architectural boundary between billing domain logic and authorization enforcement + +## Problem Statement + +Billing operations require organization-scoped authorization that differs from general administrative permissions, necessitating a consistent mechanism to enforce that only authorized users can manage billing concerns for specific organizations while maintaining clear separation between billing domain logic and authorization policy enforcement. + +## Decision + +1. MUST: Organization billing controller actions MUST use [InjectOrganization] attribute to inject the organization entity into the request pipeline + +## Policy Block + +- MUST Organization billing controller actions MUST use [InjectOrganization] attribute to inject the organization entity into the request pipeline + +In scope: +- All HTTP endpoints in Bit.Api.Billing.Controllers namespace that operate on Organization entities +- Subscription management operations (purchase, plan change, update) +- Billing address retrieval and modification endpoints +- Credit management and payment method operations +- Invoice preview and tax calculation endpoints + +Out of scope: +- User-scoped billing operations that do not involve organization entities +- Public billing information endpoints that do not require authentication +- Internal billing service-to-service calls that use service authentication +- Administrative override operations with elevated privileges + +## Rationale + +- The consistent application of ManageOrganizationBillingRequirement across PreviewInvoiceController and OrganizationBillingVNextController demonstrates a deliberate architectural decision to enforce uniform authorization boundaries for billing operations +- The combination of [Authorize], [InjectOrganization], and [BindNever] attributes creates a defense-in-depth authorization pattern that prevents parameter tampering and ensures organization context is established before authorization checks +- Separating billing authorization requirements from general administrative requirements allows for fine-grained permission models where billing management can be delegated independently of other organizational administrative functions +- The pattern's 79% confidence across 2 files with domain.boundaries facet detection indicates this is an established architectural boundary rather than an ad-hoc implementation + +## Consequences + +Positive: +- Clear separation of concerns between billing domain logic and authorization policy enforcement through dedicated attributes and requirements +- Consistent authorization model across all organization billing endpoints reduces the risk of authorization bypass vulnerabilities +- Fine-grained permission delegation enables organizations to assign billing management roles without granting full administrative access +- The attribute-based authorization pattern is declarative and easily auditable through static code analysis + +Negative: +- Additional attributes on each endpoint increase boilerplate code and require developer awareness of the authorization pattern +- The three-attribute pattern ([Authorize], [InjectOrganization], [BindNever]) must be correctly applied together, creating multiple points of potential misconfiguration +- Authorization requirements spread across multiple namespaces (Bit.Api.Billing.Models.Requirements and Bit.Api.AdminConsole.Authorization.Requirements) may complicate requirement discovery +- Testing authorization behavior requires integration tests that exercise the full attribute pipeline rather than simple unit tests + +## Alternatives + +- Use a single [AuthorizeOrganizationBilling] attribute that combines authorization, injection, and binding prevention (rejected) + Rejected because: Would reduce composability and prevent reuse of [InjectOrganization] and [BindNever] attributes in non-billing contexts where different authorization requirements apply + When valid: In greenfield projects where billing authorization is the only organization-scoped authorization concern and attribute composition is not needed +- Implement authorization checks imperatively within controller action methods using injected authorization services (rejected) + Rejected because: Imperative authorization is less declarative, harder to audit, and more prone to developer error or omission compared to attribute-based enforcement + When valid: For complex authorization logic that requires runtime context beyond what can be expressed declaratively in attributes +- Use middleware-based authorization that inspects route patterns to determine organization-scoped billing endpoints (rejected) + Rejected because: Route-based authorization couples authorization policy to URL structure and makes authorization requirements less explicit at the endpoint level + When valid: In API gateways or proxy layers where centralized authorization policy enforcement is required across multiple backend services + +## Risks + +- Developers may forget to apply all three required attributes ([Authorize], [InjectOrganization], [BindNever]) when creating new billing endpoints, creating authorization gaps + Mitigation: Implement custom Roslyn analyzers or linting rules that detect billing controller methods missing the required attribute combination and fail CI builds + Owner: Security Engineering Team +- Changes to the ManageOrganizationBillingRequirement implementation could inadvertently weaken authorization checks across all billing endpoints + Mitigation: Maintain comprehensive integration tests for authorization requirements and require security team review for changes to authorization requirement implementations + Owner: Security Engineering Team +- The [BindNever] attribute prevents model binding but does not prevent developers from accidentally using organizationId route parameters directly without authorization + Mitigation: Code review guidelines must emphasize that organization context must only come from [InjectOrganization] and never from route parameters or request body + Owner: Engineering Team + +## Implementation Notes + +- When creating new billing endpoints in Bit.Api.Billing.Controllers, always apply the three-attribute pattern: [Authorize], [InjectOrganization], and [BindNever] on the organization parameter +- Ensure that Organization entities are always injected via [InjectOrganization] and never constructed from route parameters or request body data to prevent parameter tampering +- Place billing-specific authorization requirements in Bit.Api.Billing.Models.Requirements namespace to maintain clear separation from general administrative requirements +- Use consistent parameter naming (organization) and binding attributes ([BindNever]) across all billing endpoints to establish recognizable patterns during code review + +## Continuation Context + + +Verify commands: +- grep -r "class.*Controller.*Billing" src/Api/Billing/Controllers/ | xargs -I {} sh -c 'grep -L "Authorize" {} && echo "Missing authorization: {}"' +- grep -r "\[InjectOrganization\]" src/Api/Billing/Controllers/ -A 3 | grep -v "\[BindNever\]" | grep "Organization organization" && echo "Found Organization parameter without [BindNever]" || echo "All Organization parameters properly protected" +- find src/Api/Billing/Controllers -name "*.cs" -exec grep -l "public async Task" {} \; | xargs grep -L "Authorize" | grep -v "Test" || echo "All billing endpoints have authorization" + +Accept when: +- All controller methods in Bit.Api.Billing.Controllers namespace that accept Organization parameters are decorated with [Authorize] +- All Organization parameters in billing endpoints are marked with [BindNever] and injected via [InjectOrganization] +- Grep verification commands return no violations for missing authorization attributes or unprotected Organization parameters + +## Enforcement + +- Verified by: Automated static analysis using custom Roslyn analyzers that detect billing controller methods missing required authorization attributes +- Verified by: Code review checklist items requiring verification of the three-attribute pattern on all organization billing endpoints +- Verified by: Integration tests that verify authorization enforcement by attempting to access billing endpoints without proper organization permissions +- Violation handling: CI pipeline failures when static analysis detects missing authorization attributes on billing endpoints +- Violation handling: Code review rejection for pull requests that introduce billing endpoints without the required attribute combination +- Violation handling: Security team notification for any authorization requirement implementation changes that affect billing operations +- Exception process: Exceptions to the organization-scoped authorization pattern require written justification documenting the alternative authorization mechanism +- Exception process: Security team approval is required for any billing endpoint that does not use ManageOrganizationBillingRequirement +- Exception process: Approved exceptions must be documented in code comments with reference to the security team approval ticket \ No newline at end of file diff --git a/docs/adr/daae2af9-369d-4fcc-b20a-d10c0f1d03f6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md b/docs/adr/daae2af9-369d-4fcc-b20a-d10c0f1d03f6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md new file mode 100644 index 000000000000..ace4dfc29b1c --- /dev/null +++ b/docs/adr/daae2af9-369d-4fcc-b20a-d10c0f1d03f6-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md @@ -0,0 +1,119 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Returning + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic operations (key generation, cipher encryption/decryption) through a C-compatible FFI boundary to enable interoperability with non-Rust codebases +- FFI functions accept raw C string pointers (c_char) from external callers, requiring explicit conversion to safe Rust string types to prevent undefined behavior from null pointers, invalid UTF-8, or missing null terminators +- The codebase uses std::ffi::{CStr, CString} for bidirectional string marshaling across the FFI boundary in lib.rs and cipher.rs +- Base64 encoding/decoding operations in cipher.rs handle binary cryptographic data that crosses the FFI boundary as string representations +- The pattern appears in 2 files with 90.85% confidence, indicating consistent application of FFI string validation practices in security-sensitive cryptographic code + +## Problem Statement + +Raw C string pointers passed across FFI boundaries are inherently unsafe and can cause memory corruption, crashes, or security vulnerabilities if not properly validated and converted to Rust's safe string types before use in cryptographic operations. + +## Decision + +1. MUST: FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function for memory cleanup + +## Policy Block + +- MUST FFI functions returning strings to C callers MUST use CString::into_raw to transfer ownership and provide a corresponding free_c_string function for memory cleanup + +In scope: +- All public FFI functions in the Rust SDK that accept or return string parameters +- Cryptographic operations exposed through FFI including key generation, encryption, and decryption functions +- String marshaling code in lib.rs and cipher.rs modules +- Base64 encoding/decoding operations for binary cryptographic data + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- Non-string FFI parameters such as integers, booleans, or opaque pointers +- String operations in pure Rust code using native String or &str types +- FFI functions that only accept or return primitive types + +## Rationale + +- The evidence shows consistent use of std::ffi::{c_char, CStr, CString} across 2 files in security-sensitive cryptographic code, indicating a deliberate pattern for safe FFI string handling +- CStr/CString conversion is the idiomatic Rust approach for validating C strings at FFI boundaries, preventing undefined behavior from malformed input +- The pattern appears in both lib.rs (key generation functions) and cipher.rs (encryption/decryption functions), demonstrating application across the entire cryptographic API surface +- Base64 encoding integration suggests the pattern extends to handling binary-to-text conversions required for transmitting cryptographic data across FFI boundaries + +## Consequences + +Positive: +- Prevents memory safety vulnerabilities from malformed C strings including null pointer dereferences, buffer overruns, and invalid UTF-8 sequences +- Provides clear ownership semantics for string memory across the FFI boundary with explicit allocation and deallocation functions +- Enables safe interoperability between Rust cryptographic implementations and C/C++ codebases without compromising Rust's safety guarantees +- Establishes a consistent validation pattern that can be audited and verified across all FFI entry points + +Negative: +- Adds runtime overhead for string validation and conversion on every FFI call, potentially impacting performance in high-throughput scenarios +- Requires careful memory management discipline from C callers to invoke free_c_string for returned strings, risking memory leaks if not properly documented +- Increases code complexity with unsafe blocks and error handling logic at every FFI boundary +- May introduce subtle bugs if CString::into_raw ownership transfer is not correctly paired with deallocation + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated C strings (rejected) + Rejected because: Would require more complex FFI signatures and caller-side changes; C string convention is standard for interoperability with existing C/C++ codebases + When valid: When integrating with systems that already use length-prefixed buffers or when null bytes are valid data +- Use higher-level FFI binding generators like cbindgen or cxx crate for automated safe bindings (rejected) + Rejected because: Evidence shows manual FFI implementation is already in place; migration would require significant refactoring of existing API contracts + When valid: For new FFI interfaces or when redesigning the SDK API from scratch +- Panic on invalid string input rather than returning error codes (rejected) + Rejected because: Panicking across FFI boundaries causes undefined behavior in C callers; error codes provide safer failure handling + When valid: Never appropriate for FFI boundaries; only acceptable in pure Rust code + +## Risks + +- C callers may forget to call free_c_string on returned strings, causing memory leaks that accumulate over time + Mitigation: Document memory ownership clearly in API documentation; consider providing language-specific wrapper libraries that automate cleanup; add memory leak detection in integration tests + Owner: SDK engineering team +- Unsafe blocks required for CStr::from_ptr may hide other memory safety issues if not carefully reviewed + Mitigation: Limit unsafe block scope to minimal string conversion operations; require peer review for all FFI code changes; use Miri and sanitizers in CI to detect undefined behavior + Owner: Security review team +- Performance overhead from string validation may become bottleneck in high-frequency cryptographic operations + Mitigation: Profile FFI call overhead in realistic workloads; consider batch APIs that amortize validation cost; document performance characteristics for callers + Owner: Performance engineering team + +## Implementation Notes + +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks using is_null() before dereferencing +- Provide a public free_c_string function that accepts *mut c_char and calls CString::from_raw followed by automatic drop +- Use CStr::to_str() or to_string_lossy() to convert validated C strings to Rust &str or String types for internal processing +- Document the memory ownership contract in function comments: callers own input strings, Rust SDK owns returned strings until free_c_string is called +- Consider adding FFI integration tests that verify correct behavior with null pointers, invalid UTF-8, and missing null terminators + +## Continuation Context + + +Verify commands: +- grep -r "CStr::from_ptr" util/RustSdk/rust/src/ | grep -v "unsafe" && echo "FAIL: CStr::from_ptr used outside unsafe block" || echo "PASS" +- grep -r "pub.*fn.*c_char" util/RustSdk/rust/src/ | wc -l +- grep -r "free_c_string" util/RustSdk/rust/src/ | grep "pub fn" && echo "PASS: free_c_string function exists" || echo "FAIL" + +Accept when: +- All CStr::from_ptr conversions are contained within unsafe blocks with null pointer validation +- A public free_c_string function exists and is documented for C callers to deallocate returned strings +- FFI functions in lib.rs and cipher.rs consistently use CStr/CString for string parameter marshaling +- Base64 encoding/decoding uses the standard engine from the base64 crate for cryptographic data + +## Enforcement + +- Verified by: Code review checklist requiring verification of CStr/CString usage in all FFI functions +- Verified by: Static analysis with clippy lints for unsafe FFI patterns +- Verified by: Integration tests exercising FFI boundary with invalid inputs (null pointers, invalid UTF-8) +- Verified by: Miri execution in CI to detect undefined behavior in unsafe blocks +- Violation handling: Pull requests introducing FFI functions without proper CStr/CString validation are blocked in code review +- Violation handling: Clippy warnings for unsafe FFI patterns are treated as build failures in CI +- Violation handling: Security team conducts quarterly audits of all FFI boundary code for compliance +- Violation handling: Violations discovered in production trigger immediate security review and hotfix process +- Exception process: Exceptions require written justification documenting why alternative validation is equivalent or superior +- Exception process: Security team must approve all exceptions with explicit risk assessment +- Exception process: Exceptions are time-limited (maximum 6 months) and require re-approval or remediation +- Exception process: All approved exceptions are tracked in a central registry with assigned owners and expiration dates \ No newline at end of file diff --git a/docs/adr/db430582-fad9-41d5-92df-f2d3f63b417b-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-messages-describe.md b/docs/adr/db430582-fad9-41d5-92df-f2d3f63b417b-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-messages-describe.md new file mode 100644 index 000000000000..c2adaeb413ee --- /dev/null +++ b/docs/adr/db430582-fad9-41d5-92df-f2d3f63b417b-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-messages-describe.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Messages Describe + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. SHOULD: Log messages SHOULD describe the operation outcome and context (e.g., 'Failed to update Stripe customer for provider {ProviderId}. Database was updated successfully.') to aid correlation with authorization events + +## Policy Block + +- SHOULD Log messages SHOULD describe the operation outcome and context (e.g., 'Failed to update Stripe customer for provider {ProviderId}. Database was updated successfully.') to aid correlation with authorization events + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/db813764-d050-4876-94d4-0e28cba2b6e0-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-requirements-named.md b/docs/adr/db813764-d050-4876-94d4-0e28cba2b6e0-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-requirements-named.md new file mode 100644 index 000000000000..2e50383a5b3d --- /dev/null +++ b/docs/adr/db813764-d050-4876-94d4-0e28cba2b6e0-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-authorization-requirements-named.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Authorization Requirements Named + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. SHOULD: Authorization requirements SHOULD be named with a Requirement suffix to clearly identify them as authorization requirement types + +## Policy Block + +- SHOULD Authorization requirements SHOULD be named with a Requirement suffix to clearly identify them as authorization requirement types + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/dbd8aab1-ab4a-4f5a-8ffb-becc2a19bfa1-standardize-authorization-policy-configuration-with-named-scopes-authorization-policies-configured.md b/docs/adr/dbd8aab1-ab4a-4f5a-8ffb-becc2a19bfa1-standardize-authorization-policy-configuration-with-named-scopes-authorization-policies-configured.md new file mode 100644 index 000000000000..81579f59c8fc --- /dev/null +++ b/docs/adr/dbd8aab1-ab4a-4f5a-8ffb-becc2a19bfa1-standardize-authorization-policy-configuration-with-named-scopes-authorization-policies-configured.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Authorization Policies Configured + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. MUST: Authorization policies MUST be configured using AddAuthorization with explicitly named policy identifiers + +## Policy Block + +- MUST Authorization policies MUST be configured using AddAuthorization with explicitly named policy identifiers + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/dcb80ee8-6360-45cd-b6b0-608633a0450d-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-ffi-entry-points.md b/docs/adr/dcb80ee8-6360-45cd-b6b0-608633a0450d-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-ffi-entry-points.md new file mode 100644 index 000000000000..57785b49a738 --- /dev/null +++ b/docs/adr/dcb80ee8-6360-45cd-b6b0-608633a0450d-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-ffi-entry-points.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Ffi Entry Points + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. MUST: All FFI entry points handling key material MUST implement input validation for C string parameters before conversion to Rust types + +## Policy Block + +- MUST All FFI entry points handling key material MUST implement input validation for C string parameters before conversion to Rust types + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/de1c22f9-d8ba-4eca-bb3e-ea5d64b8e226-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-that.md b/docs/adr/de1c22f9-d8ba-4eca-bb3e-ea5d64b8e226-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-that.md new file mode 100644 index 000000000000..d0f58734027a --- /dev/null +++ b/docs/adr/de1c22f9-d8ba-4eca-bb3e-ea5d64b8e226-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-that.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Verify That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. SHOULD: Tests SHOULD verify that repository methods were called with expected parameters using mock verification (Received, DidNotReceiveWithAnyArgs) to confirm external boundary interactions + +## Policy Block + +- SHOULD Tests SHOULD verify that repository methods were called with expected parameters using mock verification (Received, DidNotReceiveWithAnyArgs) to confirm external boundary interactions + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/de8d2acb-b47a-439b-a60e-efe4b11cee60-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-controllers-use-base.md b/docs/adr/de8d2acb-b47a-439b-a60e-efe4b11cee60-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-controllers-use-base.md new file mode 100644 index 000000000000..21f73820d053 --- /dev/null +++ b/docs/adr/de8d2acb-b47a-439b-a60e-efe4b11cee60-enforce-generic-authorize-attribute-with-typed-requirements-for-api-authorization-controllers-use-base.md @@ -0,0 +1,121 @@ +# Enforce Generic Authorize Attribute with Typed Requirements for API Authorization: Controllers Use Base + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller endpoints requiring authorization in the AdminConsole API surface. + +## Context + +- The AdminConsole API exposes organization and provider management endpoints that require fine-grained authorization beyond simple role checks +- Controllers in the Bit.Api.AdminConsole namespace handle sensitive operations including policy management, organization invite links, and provider-organization relationships +- The ASP.NET Core authorization framework provides attribute-based authorization but requires a consistent pattern for expressing typed requirements +- Multiple authorization requirements exist (ManageUsersRequirement, ManagePoliciesRequirement, ProviderUserRequirement, ProviderAdminRequirement, OrgUserLinkedToUserIdRequirement) that must be enforced at the endpoint level +- The codebase demonstrates a pattern of using generic Authorize attributes on HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) to declare authorization constraints + +## Problem Statement + +API endpoints in the AdminConsole surface require a standardized mechanism to declare authorization requirements that is type-safe, discoverable, and integrates with the ASP.NET Core authorization pipeline. Without a consistent authorization model, endpoints risk inconsistent security enforcement, difficult-to-audit authorization logic, and increased likelihood of authorization bypass vulnerabilities. + +## Decision + +1. MUST: Controllers MUST use the base Authorize attribute with "Application" parameter at the class level to enforce application-level authentication before requirement-specific authorization + +## Policy Block + +- MUST Controllers MUST use the base Authorize attribute with "Application" parameter at the class level to enforce application-level authentication before requirement-specific authorization + +In scope: +- All controllers in the Bit.Api.AdminConsole.Controllers namespace +- All HTTP verb-decorated methods (HttpGet, HttpPost, HttpPut, HttpDelete) that handle authenticated requests +- Authorization requirement classes in Bit.Api.AdminConsole.Authorization and its subnamespaces + +Out of scope: +- Public endpoints explicitly marked with AllowAnonymous (e.g., token-based policy retrieval) +- Health check or diagnostic endpoints that do not access protected resources +- Authorization handlers and requirement implementation classes themselves + +Exceptions: +- EXC-001: Endpoints that validate tokens or provide pre-authentication information (e.g., GetByToken in PoliciesController) +- EXC-002: Deprecated endpoints maintaining backward compatibility (e.g., PostDelete methods) + +## Rationale + +- The pattern appears consistently across 3 controller files (OrganizationInviteLinksController, ProviderOrganizationsController, PoliciesController) with 79.13% confidence, indicating an established architectural convention +- Generic Authorize attributes provide compile-time type safety and enable IDE tooling to discover authorization requirements across the codebase +- Declarative authorization at the method level makes security boundaries explicit and auditable without requiring inspection of method bodies +- The pattern integrates with ASP.NET Core's IAuthorizationRequirement and IAuthorizationHandler infrastructure, enabling centralized authorization logic and testability + +## Consequences + +Positive: +- Authorization requirements are discoverable through static analysis and IDE navigation, improving security auditability +- Type-safe authorization attributes prevent runtime errors from misspelled requirement names or incorrect parameter types +- Centralized authorization handlers enable consistent enforcement of business rules across multiple endpoints +- Clear separation between authentication (Authorize with Application) and authorization (Authorize) simplifies security reasoning + +Negative: +- Requires defining separate requirement classes for each authorization concern, increasing the number of types in the codebase +- Complex authorization logic that depends on request parameters may still require imperative checks within method bodies (e.g., ICurrentContext.OrganizationOwner checks) +- Developers must understand both the ASP.NET Core authorization framework and the custom requirement types to implement new endpoints correctly +- Refactoring authorization requirements may require changes across multiple controller methods and handler implementations + +## Alternatives + +- Use string-based Authorize(Policy = "PolicyName") attributes with policy names registered in startup configuration (rejected) + Rejected because: String-based policy names lack compile-time safety, are not refactoring-friendly, and make it difficult to discover all usages of a policy across the codebase + When valid: May be appropriate for simple role-based authorization that does not require custom requirement types +- Implement authorization checks imperatively within each controller method using ICurrentContext or authorization services (rejected) + Rejected because: Imperative authorization logic is harder to audit, test, and maintain consistently across endpoints, and does not integrate with ASP.NET Core's authorization pipeline for middleware-level enforcement + When valid: Acceptable as a supplement to declarative authorization for complex business rules that depend on request body content or multiple data sources +- Use custom authorization filters or action filters to enforce authorization requirements (rejected) + Rejected because: Custom filters bypass the standard ASP.NET Core authorization infrastructure, making it harder to integrate with existing authorization middleware, policies, and testing tools + When valid: May be appropriate for cross-cutting authorization concerns that apply to many endpoints and require custom execution order + +## Risks + +- Developers may forget to apply authorization attributes to new endpoints, creating authorization bypass vulnerabilities + Mitigation: Implement static analysis rules or linters that flag controller methods without authorization attributes; establish code review checklist items for authorization verification + Owner: Security team and engineering team +- Complex authorization logic split between declarative attributes and imperative checks may create confusion about the complete authorization model + Mitigation: Document the authorization decision tree for each endpoint; establish guidelines for when to use declarative vs. imperative authorization; require security review for endpoints with mixed authorization approaches + Owner: Architecture team +- Changes to requirement classes or authorization handlers may inadvertently affect multiple endpoints in unexpected ways + Mitigation: Maintain comprehensive integration tests for authorization scenarios; use dependency analysis tools to identify all endpoints affected by requirement changes; require security regression testing for authorization handler modifications + Owner: Engineering team + +## Implementation Notes + +- Define new authorization requirement classes in Bit.Api.AdminConsole.Authorization.Requirements with a Requirement suffix (e.g., ManageUsersRequirement, ManagePoliciesRequirement) +- Apply [Authorize("Application")] at the controller class level to enforce base authentication, then apply [Authorize] at the method level for specific authorization requirements +- For endpoints that require multiple authorization checks, combine declarative Authorize attributes with imperative ICurrentContext checks, documenting the rationale for the imperative checks +- Use AllowAnonymous explicitly on public endpoints to document the intentional bypass of authorization and facilitate security audits +- Implement IAuthorizationHandler classes to centralize authorization logic and enable unit testing of authorization decisions independently of controller logic + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api/AdminConsole/Controllers/ | wc -l +- grep -r "public async Task" src/Api/AdminConsole/Controllers/ | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" | wc -l +- find src/Api/AdminConsole/Authorization -name "*Requirement.cs" | wc -l + +Accept when: +- All controller methods in AdminConsole that access protected resources have either [Authorize] or [AllowAnonymous] attributes +- All requirement classes are defined in Bit.Api.AdminConsole.Authorization namespace or subnamespaces and follow the Requirement naming suffix convention +- No controller methods use string-based Authorize(Policy = "...") attributes for authorization requirements + +## Enforcement + +- Verified by: Static analysis during CI pipeline using custom Roslyn analyzers or linting rules +- Verified by: Code review checklist requiring verification of authorization attributes on all new endpoints +- Verified by: Security-focused integration tests that verify authorization enforcement for each endpoint +- Violation handling: CI pipeline fails if controller methods lack authorization attributes +- Violation handling: Code review blocks merge until authorization attributes are properly applied +- Violation handling: Security team conducts quarterly audits of authorization patterns and reports violations to engineering leadership +- Exception process: Developer documents the security rationale for the exception in code comments and ADR exception log +- Exception process: Security team reviews and approves the exception request with documented risk assessment +- Exception process: Exception is tracked in a security exceptions register with periodic review cadence \ No newline at end of file diff --git a/docs/adr/de9f504d-885a-43ed-b247-3dfd6643354a-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verifying-exceptions.md b/docs/adr/de9f504d-885a-43ed-b247-3dfd6643354a-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verifying-exceptions.md new file mode 100644 index 000000000000..d1eebc08e6b9 --- /dev/null +++ b/docs/adr/de9f504d-885a-43ed-b247-3dfd6643354a-adopt-async-await-pattern-for-unit-test-assertions-in-testing-strategy-tests-verifying-exceptions.md @@ -0,0 +1,113 @@ +# Adopt Async/Await Pattern for Unit Test Assertions in Testing Strategy: Tests Verifying Exceptions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase contains unit tests for SCIM group management (PatchGroupCommandTests.cs) and access policy queries (SameOrganizationQueryTests.cs) that interact with asynchronous repository and command operations +- Test methods use async/await patterns to invoke system-under-test methods that return Task or Task, requiring asynchronous assertion patterns +- Dependencies include Bit.Core.AdminConsole repositories, AutoFixture for test data generation, and NSubstitute for mocking asynchronous operations +- Tests verify behavior of commands and queries that coordinate multiple asynchronous operations including repository updates, group commands, and organization validation + +## Problem Statement + +Unit tests for asynchronous application logic require a consistent approach to invoking async methods and asserting on their results or exceptions, ensuring tests properly await operations, verify call sequences on mocked dependencies, and validate both success and failure paths without blocking or introducing race conditions. + +## Decision + +1. MUST: Tests verifying exceptions from async methods MUST use Assert.ThrowsAsync with await rather than synchronous assertion methods + +## Policy Block + +- MUST Tests verifying exceptions from async methods MUST use Assert.ThrowsAsync with await rather than synchronous assertion methods + +In scope: +- Unit tests for asynchronous commands and queries in Bit.Core.AdminConsole +- Unit tests for Bit.Commercial.Core.SecretsManager components +- Test classes using AutoFixture and NSubstitute for dependency mocking +- Tests verifying repository operations that return Task or Task + +Out of scope: +- Integration tests that interact with actual database connections +- Synchronous business logic that does not use async/await +- End-to-end tests using test servers or HTTP clients +- Performance or load tests with specialized async patterns + +## Rationale + +- The evidence shows consistent use of async/await in test methods across PatchGroupCommandTests.cs and SameOrganizationQueryTests.cs, with await applied to sutProvider.Sut method calls and Assert.ThrowsAsync +- Tests verify asynchronous operations on IGroupRepository, IUpdateGroupCommand, and organization/group repositories using Received() after awaiting the system under test +- The pattern enables proper testing of asynchronous coordination logic including UpdateUsersAsync, UpdateGroupAsync, OrgUsersInTheSameOrgAsync, and GroupsInTheSameOrgAsync methods +- Using async/await in tests ensures proper task completion, exception propagation, and verification of call sequences without deadlocks or race conditions + +## Consequences + +Positive: +- Tests accurately verify asynchronous behavior without blocking threads or introducing timing issues +- Exception handling paths in async methods can be properly tested using Assert.ThrowsAsync +- Mock verification with Received() occurs after async operations complete, ensuring correct call order validation +- Test code structure mirrors production async/await patterns, improving readability and maintainability + +Negative: +- Async test methods may have slightly longer execution time due to task scheduling overhead +- Debugging async test failures can be more complex due to state machine transformations and stack traces +- Developers must understand async/await semantics to avoid common pitfalls like missing await keywords +- Test frameworks must support async test methods, which may limit compatibility with older testing tools + +## Alternatives + +- Use synchronous blocking with .Result or .Wait() on Task-returning methods (rejected) + Rejected because: Blocking on async methods can cause deadlocks in certain synchronization contexts and does not properly test async exception handling or cancellation behavior + When valid: Only valid for quick prototypes or when absolutely certain no synchronization context exists +- Use Task.Run to wrap synchronous test code and execute async methods (rejected) + Rejected because: Introduces unnecessary thread pool scheduling and obscures the actual async control flow being tested, making verification of call sequences unreliable + When valid: May be valid for testing specific thread pool or synchronization context behavior +- Use async void test methods instead of async Task (rejected) + Rejected because: Async void methods cannot be awaited by test runners, leading to test completion before async operations finish and unreliable test results + When valid: Never valid for unit tests; only appropriate for event handlers in production code + +## Risks + +- Developers may forget await keyword, causing tests to complete before async operations finish and producing false positives + Mitigation: Enable compiler warnings for unawaited tasks and use code analysis rules to detect missing await in test methods + Owner: Engineering team +- Complex async test scenarios with multiple awaited operations may become difficult to debug when failures occur + Mitigation: Structure tests with clear arrange-act-assert phases, use descriptive test names, and add logging for async operation boundaries + Owner: Engineering team +- Mock verification timing issues may occur if Received() is called before async operations complete + Mitigation: Always await system-under-test invocations before calling Received() verification methods on mocked dependencies + Owner: Engineering team + +## Implementation Notes + +- Declare test methods as 'public async Task MethodName_Scenario_ExpectedResult()' when testing async system-under-test methods +- Use 'await Assert.ThrowsAsync(() => sutProvider.Sut.AsyncMethod(...))' for exception testing +- Configure AutoFixture and sutProvider in test class constructor or setup method, then await SUT invocations in individual test methods +- When verifying repository calls with Received(), use Arg.Is with lambda expressions to validate collection contents and DateTime parameters match expected values + +## Continuation Context + + +Verify commands: +- grep -r 'public async Task.*Test' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'await.*sutProvider\.Sut\.' bitwarden_license/test/ --include='*.cs' | wc -l +- grep -r 'Assert\.ThrowsAsync' bitwarden_license/test/ --include='*.cs' | wc -l + +Accept when: +- All test methods invoking async system-under-test methods are declared as async Task and use await +- Exception testing for async methods uses Assert.ThrowsAsync with await rather than synchronous assertions +- Mock verification with Received() occurs after awaiting system-under-test invocations in all test cases + +## Enforcement + +- Verified by: Code review checklist requiring async/await pattern verification in test methods +- Verified by: Static analysis rules detecting unawaited Task-returning calls in test methods +- Verified by: CI pipeline test execution ensuring all async tests complete successfully +- Violation handling: Pull requests with synchronous blocking (.Result, .Wait()) on async methods in tests are rejected +- Violation handling: Compiler warnings for unawaited tasks in test projects are treated as errors +- Violation handling: Test failures due to timing issues or incomplete async operations trigger investigation of await usage +- Exception process: Exceptions require architectural review if synchronous test patterns are needed for specific scenarios +- Exception process: Document rationale in test comments if alternative async patterns are required for specialized testing +- Exception process: Obtain approval from tech lead before using Task.Run or other non-standard async test patterns \ No newline at end of file diff --git a/docs/adr/dff2c838-b9c1-4a48-8adb-8c612733d23b-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-public-endpoints-that.md b/docs/adr/dff2c838-b9c1-4a48-8adb-8c612733d23b-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-public-endpoints-that.md new file mode 100644 index 000000000000..fe554e3ec177 --- /dev/null +++ b/docs/adr/dff2c838-b9c1-4a48-8adb-8c612733d23b-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-public-endpoints-that.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Public Endpoints That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. SHOULD: Public endpoints that do not require authentication SHOULD be explicitly marked with [AllowAnonymous] to document the intentional absence of authorization + +## Policy Block + +- SHOULD Public endpoints that do not require authentication SHOULD be explicitly marked with [AllowAnonymous] to document the intentional absence of authorization + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/e0ea0450-c5af-4e11-a0b5-871bc1543346-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-internal-controller-actions.md b/docs/adr/e0ea0450-c5af-4e11-a0b5-871bc1543346-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-internal-controller-actions.md new file mode 100644 index 000000000000..044681542715 --- /dev/null +++ b/docs/adr/e0ea0450-c5af-4e11-a0b5-871bc1543346-adopt-authorize-attribute-based-authorization-for-internal-api-endpoints-internal-controller-actions.md @@ -0,0 +1,118 @@ +# Adopt Authorize Attribute-Based Authorization for Internal API Endpoints: Internal Controller Actions + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all internal API endpoint implementations requiring authorization enforcement. + +## Context + +- Internal API endpoints in the AdminConsole and Admin controllers require consistent authorization enforcement to protect organization-level resources and administrative functions +- The codebase uses ASP.NET Core's authorization framework with custom requirement-based authorization attributes (Authorize) applied at the controller action level +- Multiple endpoints managing organization invite links and administrative functions share a common authorization model pattern across 2 detected files with 79.75% confidence +- Authorization decisions are declaratively expressed through attributes rather than imperative checks within action methods, separating authorization concerns from business logic + +## Problem Statement + +Internal API endpoints must enforce consistent authorization policies to prevent unauthorized access to organization management and administrative functions, while maintaining clear separation between authorization logic and business logic implementation. + +## Decision + +1. MUST: All internal API controller actions that manage organization resources MUST apply authorization attributes (e.g., [Authorize]) to enforce access control + +## Policy Block + +- MUST All internal API controller actions that manage organization resources MUST apply authorization attributes (e.g., [Authorize]) to enforce access control + +In scope: +- All controller actions in Bit.Api.AdminConsole.Controllers namespace managing organization resources +- All controller actions in Bit.Admin.Controllers namespace requiring authenticated access +- HTTP endpoints exposed through ASP.NET Core routing that access organization-scoped data or administrative functions + +Out of scope: +- Public API endpoints explicitly designed for unauthenticated access (e.g., health checks, version endpoints) +- Authorization handler implementation logic (covered by separate authorization framework patterns) +- Client-side authorization checks or UI-level access control + +Exceptions: +- EXC-001: Public endpoints that validate organization invite link codes or retrieve public organization information without requiring authentication + +## Rationale + +- Evidence shows consistent application of [Authorize] across all organization invite link management endpoints (Get, Create, Update, Delete, Refresh) in OrganizationInviteLinksController, demonstrating a standardized authorization pattern +- The pattern separates authorization concerns from business logic by using declarative attributes, enabling centralized authorization policy management and reducing code duplication across 2 detected controller files +- ASP.NET Core's attribute-based authorization integrates with the framework's middleware pipeline, providing consistent enforcement before action method execution and enabling testable authorization handlers +- The detected pattern aligns with the principle of least privilege by requiring explicit authorization declarations rather than defaulting to open access + +## Consequences + +Positive: +- Consistent authorization enforcement across all internal API endpoints reduces the risk of unauthorized access to organization resources +- Declarative authorization attributes improve code readability and make security requirements explicit at the endpoint definition level +- Centralized authorization handlers enable reusable authorization logic and simplify security audits by consolidating policy definitions +- Framework-integrated authorization provides automatic HTTP 401/403 responses and integrates with authentication middleware without custom implementation + +Negative: +- Attribute-based authorization requires understanding of ASP.NET Core's authorization framework and custom requirement classes, increasing learning curve for new developers +- Complex authorization scenarios may require multiple attributes or custom authorization handlers, potentially leading to scattered authorization logic +- Debugging authorization failures can be challenging as the decision logic is external to the controller action and requires examining authorization handler implementations + +## Alternatives + +- Implement imperative authorization checks within each controller action method using injected authorization services (rejected) + Rejected because: Imperative checks scatter authorization logic across action methods, increase code duplication, and make security audits more difficult. The declarative approach provides better separation of concerns and framework integration. + When valid: May be appropriate for highly dynamic authorization scenarios where the authorization decision depends on complex runtime state not available at attribute evaluation time +- Apply authorization attributes at the controller class level rather than individual action methods (rejected) + Rejected because: Class-level authorization reduces granularity and makes it difficult to apply different authorization requirements to different actions (e.g., read vs. write operations). Action-level attributes provide finer-grained control. + When valid: Appropriate when all actions in a controller require identical authorization requirements and no action-specific policies are needed +- Use policy-based authorization with string-based policy names instead of typed requirement classes (deferred) + Rejected because: Not rejected; this is a valid alternative that trades compile-time safety for simpler syntax. The current typed requirement approach provides better refactoring support and IDE assistance. + When valid: Suitable for simpler authorization scenarios where the benefits of typed requirements do not outweigh the additional complexity + +## Risks + +- Missing authorization attributes on new endpoints could expose unauthorized access if developers forget to apply attributes during implementation + Mitigation: Implement automated security testing that verifies all internal API endpoints have authorization attributes. Add code review checklist items for authorization verification. Consider default-deny policies at the routing level. + Owner: Security team and engineering team +- Authorization handler bugs or misconfigurations could grant excessive permissions or deny legitimate access across multiple endpoints + Mitigation: Implement comprehensive unit tests for authorization handlers. Conduct regular security audits of authorization policies. Use integration tests to verify end-to-end authorization behavior. + Owner: Security team +- Performance impact from authorization handler execution on every request could affect API response times under high load + Mitigation: Profile authorization handler performance and optimize expensive operations. Consider caching authorization decisions where appropriate. Monitor API latency metrics to detect authorization-related performance degradation. + Owner: Engineering team + +## Implementation Notes + +- Create custom authorization requirement classes by implementing IAuthorizationRequirement interface and corresponding authorization handlers that inherit from AuthorizationHandler +- Register authorization handlers in the dependency injection container during application startup (typically in Program.cs or Startup.cs) +- Apply [Authorize] attributes to controller actions, ensuring the generic type parameter matches the registered requirement class +- For endpoints requiring multiple authorization checks, apply multiple authorization attributes or create composite requirement classes that encapsulate multiple authorization rules +- Document public endpoints with [AllowAnonymous] attribute and include security rationale in code comments to distinguish intentional public access from missing authorization + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -v "\[AllowAnonymous\]" | wc -l +- grep -r "public.*Task\|public.*IActionResult" src/Api/AdminConsole/Controllers/ src/Admin/Controllers/ | grep -B5 "\[Authorize" | grep -c "public" +- dotnet test --filter "Category=Authorization" --no-build --verbosity normal + +Accept when: +- All internal API controller actions managing organization resources have authorization attributes applied, verified by grep showing 100% coverage of non-public endpoints +- Authorization handler unit tests pass with at least 90% code coverage for all custom requirement classes +- Integration tests verify that unauthorized requests to protected endpoints return HTTP 401 or 403 status codes + +## Enforcement + +- Verified by: Automated security tests in CI pipeline that scan for controller actions without authorization attributes +- Verified by: Code review checklist requiring explicit verification of authorization attributes on new or modified endpoints +- Verified by: Static analysis tools configured to flag public controller actions missing authorization attributes +- Violation handling: CI pipeline fails if security tests detect endpoints without required authorization attributes +- Violation handling: Code review process blocks merge requests that add or modify endpoints without proper authorization +- Violation handling: Security team conducts quarterly audits and files remediation tickets for any violations discovered +- Exception process: Developer documents the security rationale for public endpoint access in code comments and ADR exception request +- Exception process: Security team reviews exception request and assesses data exposure risk and authentication bypass justification +- Exception process: Approved exceptions require [AllowAnonymous] attribute with accompanying comment referencing the exception approval \ No newline at end of file diff --git a/docs/adr/e1776714-355e-4af4-8981-ebbc0835371b-adopt-http-client-abstraction-for-external-service-integration-services-implement-custom.md b/docs/adr/e1776714-355e-4af4-8981-ebbc0835371b-adopt-http-client-abstraction-for-external-service-integration-services-implement-custom.md new file mode 100644 index 000000000000..df020bad17c9 --- /dev/null +++ b/docs/adr/e1776714-355e-4af4-8981-ebbc0835371b-adopt-http-client-abstraction-for-external-service-integration-services-implement-custom.md @@ -0,0 +1,115 @@ +# Adopt HTTP Client Abstraction for External Service Integration: Services Implement Custom + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase integrates with external services and APIs requiring HTTP communication capabilities across multiple language runtimes (Rust and C#) +- Service-oriented architecture requires standardized patterns for outbound HTTP requests to external dependencies including third-party APIs, remote data sources, and distributed system components +- The system uses dependency injection patterns in C# (AddHttpClient) and FFI boundaries in Rust (c_char, CStr, CString) indicating cross-language interoperability requirements +- Redis connection multiplexer and distributed rate limiting infrastructure suggest high-volume external communication patterns requiring connection pooling and lifecycle management + +## Problem Statement + +Systems integrating with external services face challenges in managing HTTP client lifecycle, connection pooling, retry logic, timeout handling, and cross-cutting concerns like authentication and rate limiting. Without a standardized approach, each integration point may implement these concerns inconsistently, leading to resource leaks, poor performance, and maintenance burden across multiple language runtimes. + +## Decision + +1. MAY: Services MAY implement custom HTTP message handlers for cross-cutting concerns like logging, authentication token injection, or request correlation + +## Policy Block + +- MAY Services MAY implement custom HTTP message handlers for cross-cutting concerns like logging, authentication token injection, or request correlation + +In scope: +- All HTTP requests to external third-party APIs +- Outbound communication to distributed system components outside the service boundary +- Integration with external data sources requiring HTTP/HTTPS protocols +- Cross-language FFI boundaries requiring HTTP client capabilities + +Out of scope: +- Internal service-to-service communication within the same deployment boundary +- Database client connections using native protocol drivers +- Message queue or event bus communication using dedicated client libraries +- File system or blob storage access using SDK-specific clients + +## Rationale + +- Evidence shows explicit HTTP client registration (AddHttpClient) in service configuration alongside distributed infrastructure components (Redis, rate limiting), indicating architectural intent for managed external communication +- The presence of FFI string marshaling patterns (c_char, CStr, CString) in Rust cipher utilities combined with base64 encoding suggests secure cross-boundary data exchange requiring standardized HTTP transport +- Framework-provided HTTP client abstractions offer connection pooling, DNS refresh, and socket exhaustion prevention that manual HttpClient instantiation cannot provide +- Dependency injection registration enables testability through mock HTTP handlers and consistent configuration across service instances + +## Consequences + +Positive: +- Automatic connection pooling and socket reuse prevents port exhaustion and improves performance for high-volume external API calls +- Centralized HTTP client configuration enables consistent timeout, retry, and resilience policies across all external integrations +- Dependency injection support improves testability by allowing HTTP message handler mocking without modifying production code +- Framework-managed lifecycle prevents resource leaks and ensures proper disposal of HTTP connections + +Negative: +- Additional abstraction layer increases complexity for simple one-off HTTP requests that don't require advanced features +- Framework-specific HTTP client patterns create coupling to runtime environments (.NET, Rust ecosystem) limiting portability +- Improper configuration of HTTP client factories can lead to DNS caching issues or connection pool starvation under load +- Cross-language FFI boundaries require careful memory management and error handling increasing implementation complexity + +## Alternatives + +- Direct HttpClient instantiation per request without dependency injection or connection pooling (rejected) + Rejected because: Manual instantiation leads to socket exhaustion under load, lacks connection pooling benefits, and prevents centralized configuration of retry/timeout policies + When valid: Only acceptable for one-time initialization scripts or administrative tools that make infrequent HTTP requests +- Singleton HttpClient instance shared across all external service integrations (rejected) + Rejected because: Single shared instance prevents per-service configuration (different timeouts, base addresses, authentication), doesn't respect DNS TTL changes, and creates contention under high concurrency + When valid: May be acceptable for simple applications with a single external dependency and no DNS refresh requirements +- Custom HTTP client wrapper library abstracting all framework-specific implementations (deferred) + Rejected because: Requires significant engineering investment to replicate framework features and ongoing maintenance burden + When valid: Consider if multi-runtime portability becomes critical requirement or framework HTTP clients prove insufficient for specialized protocols + +## Risks + +- Misconfigured HTTP client lifetime in dependency injection container can cause DNS caching issues where clients don't respect DNS TTL changes + Mitigation: Use framework-recommended patterns (IHttpClientFactory in .NET) that automatically handle DNS refresh and connection lifecycle. Document proper registration patterns in service configuration guidelines. + Owner: Platform Engineering Team +- FFI boundary string marshaling errors in Rust-C# interop can cause memory corruption or security vulnerabilities when passing HTTP request/response data + Mitigation: Enforce use of safe FFI patterns (CStr, CString) with explicit null-termination checks. Implement comprehensive integration tests covering FFI boundary conditions and memory safety. + Owner: Security and Rust Platform Teams +- Connection pool exhaustion under high load if HTTP client timeout and concurrency limits are not properly tuned for external service characteristics + Mitigation: Establish baseline performance testing for each external integration. Monitor connection pool metrics and implement circuit breakers to prevent cascading failures. Document recommended timeout/retry configurations per service type. + Owner: SRE and Engineering Teams + +## Implementation Notes + +- In .NET services, register HTTP clients using services.AddHttpClient() with named or typed client patterns to enable per-service configuration +- For Rust FFI boundaries, use std::ffi::{CStr, CString} for string marshaling and ensure proper error handling for null pointer checks and UTF-8 validation +- Configure base addresses, default headers, and timeout policies at registration time rather than per-request to ensure consistency +- Implement correlation ID propagation through custom HTTP message handlers to enable distributed tracing across external service boundaries +- For rate-limited external APIs, integrate with AspNetCoreRateLimit or equivalent libraries and configure Redis-backed distributed counters to coordinate limits across service instances + +## Continuation Context + + +Verify commands: +- grep -r 'AddHttpClient' --include='*.cs' src/ | wc -l +- grep -r 'new HttpClient()' --include='*.cs' src/ | grep -v 'test' | wc -l +- grep -r 'std::ffi::{.*CStr' --include='*.rs' util/ | wc -l + +Accept when: +- All production services register HTTP clients through dependency injection (AddHttpClient count > 0, direct instantiation count = 0 outside tests) +- Rust FFI boundaries use safe string marshaling patterns (CStr/CString imports present in files with external communication) +- Service configuration includes timeout and retry policies for all registered HTTP clients + +## Enforcement + +- Verified by: Static analysis scanning for direct HttpClient instantiation patterns outside test contexts +- Verified by: Code review checklist requiring HTTP client registration verification for new external service integrations +- Verified by: Integration test suite validating HTTP client behavior under timeout, retry, and failure scenarios +- Violation handling: CI pipeline fails on detection of direct HttpClient instantiation in production code paths +- Violation handling: Architecture review required for any new external service integration to validate HTTP client configuration +- Violation handling: Runtime monitoring alerts on connection pool exhaustion or DNS refresh failures indicating misconfiguration +- Exception process: Document technical justification for exception including why framework HTTP client patterns are insufficient +- Exception process: Obtain approval from platform architecture team with explicit risk acknowledgment +- Exception process: Implement compensating controls (manual connection pooling, DNS refresh logic, comprehensive monitoring) +- Exception process: Schedule technical debt review within 2 quarters to reassess exception necessity \ No newline at end of file diff --git a/docs/adr/e296cb7f-ba9f-4ae7-9961-70276b3c544a-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-use-asserthelper.md b/docs/adr/e296cb7f-ba9f-4ae7-9961-70276b3c544a-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-use-asserthelper.md new file mode 100644 index 000000000000..a435d1b2034d --- /dev/null +++ b/docs/adr/e296cb7f-ba9f-4ae7-9961-70276b3c544a-standardize-json-assertion-patterns-in-oauth-token-endpoint-integration-tests-tests-use-asserthelper.md @@ -0,0 +1,117 @@ +# Standardize JSON Assertion Patterns in OAuth Token Endpoint Integration Tests: Tests Use Asserthelper + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for OAuth token endpoints require validation of JSON response structures, including nested objects like userDecryptionOptions and authentication error messages +- Tests exercise the /connect/token endpoint with various authentication flows including password grant, SSO authorization code flow, and trusted device encryption scenarios +- System.Text.Json is used for JSON parsing and validation across test files, with assertions checking JsonValueKind.Object and extracting specific property values +- Tests validate both successful authentication responses (KDF parameters, encryption keys) and failure scenarios (error messages for bad credentials, unsupported auth request flows) +- The pattern appears in ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs, both testing identity server token issuance with different authentication mechanisms + +## Problem Statement + +Integration tests for OAuth token endpoints must validate complex JSON response structures containing authentication tokens, user decryption options, and error messages, but lack a standardized approach for asserting JSON properties, leading to inconsistent test patterns and potential gaps in response validation coverage. + +## Decision + +1. MAY: Tests MAY use AssertHelper.AssertResponseTypeIs for type-safe response validation + +## Policy Block + +- MAY Tests MAY use AssertHelper.AssertResponseTypeIs for type-safe response validation + +In scope: +- Integration tests for OAuth /connect/token endpoints +- Tests validating JSON response structures from identity server authentication flows +- Password grant, authorization code, and SSO authentication test scenarios +- Tests in Identity.IntegrationTest project testing Bit.Core.Auth components + +Out of scope: +- Unit tests that mock JSON responses without actual HTTP calls +- End-to-end tests using browser automation or UI testing frameworks +- Tests for non-authentication API endpoints +- Performance or load testing of token endpoints + +## Rationale + +- The evidence shows consistent use of System.Text.Json across two test files (ResourceOwnerPasswordValidatorTests.cs and IdentityServerSsoTests.cs) for validating OAuth token endpoint responses, indicating an established pattern +- Tests validate both success paths (KDF parameters, encryption keys, userDecryptionOptions) and failure paths (error messages for bad credentials, unsupported flows), requiring structured JSON assertion approaches +- The pattern supports testing multiple authentication mechanisms (password grant, SSO, trusted device encryption) with varying response structures, necessitating flexible JSON validation +- Explicit JsonValueKind.Object assertions and property extraction patterns provide type safety and clear test failure diagnostics when response structures change + +## Consequences + +Positive: +- Consistent JSON validation patterns across integration tests improve test maintainability and readability +- Type-safe JSON parsing with System.Text.Json reduces runtime errors and provides clear compilation feedback +- Explicit assertions on security-critical properties (KDF parameters, encryption keys) ensure authentication responses meet security requirements +- Standardized error message validation enables reliable detection of authentication failure scenarios + +Negative: +- System.Text.Json dependency couples tests to specific JSON parsing implementation, requiring updates if JSON library changes +- Explicit property extraction requires test updates when response structure changes, increasing maintenance burden +- JsonValueKind assertions add verbosity to test code compared to dynamic JSON access patterns +- Pattern requires developers to understand System.Text.Json API surface for effective test authoring + +## Alternatives + +- Use dynamic JSON parsing with JObject or anonymous types for flexible property access without explicit type checking (rejected) + Rejected because: Dynamic parsing sacrifices compile-time type safety and makes tests fragile to response structure changes without clear failure diagnostics + When valid: Acceptable for exploratory testing or when response structure is highly variable and type safety is not critical +- Deserialize responses to strongly-typed DTOs matching expected response contracts (rejected) + Rejected because: Requires maintaining separate DTO classes for test purposes and may hide partial response validation issues if only subset of properties are asserted + When valid: Valid when response contracts are stable and comprehensive validation of all response properties is required +- Use JSON schema validation libraries to validate response structure against predefined schemas (rejected) + Rejected because: Adds additional dependency and complexity for validation that can be achieved with direct assertions, and schema maintenance overhead + When valid: Appropriate for complex response structures with many optional fields or when contract testing against published schemas is required + +## Risks + +- Changes to OAuth token response structure require updates across multiple test files, potentially causing widespread test failures + Mitigation: Create shared helper methods for common JSON assertion patterns and centralize response structure validation logic + Owner: engineering team +- System.Text.Json API changes in future .NET versions may require test code refactoring + Mitigation: Encapsulate JSON parsing logic in test utility classes to isolate dependency on System.Text.Json API surface + Owner: engineering team +- Incomplete JSON property assertions may allow response structure regressions to pass tests + Mitigation: Establish code review checklist for integration tests ensuring critical security properties (KDF, encryption keys, error messages) are always validated + Owner: engineering team + +## Implementation Notes + +- Use System.Text.Json.JsonDocument for parsing HTTP response content and validate JsonValueKind before property access +- Structure assertions to validate JsonValueKind.Object for complex properties, then extract and assert on nested values using GetProperty() methods +- For authentication failure tests, use Assert.Equal with explicit expected error message strings like 'Username or password is incorrect. Try again.' and 'auth request flow unsupported on unknown device' +- Construct token requests using FormUrlEncodedContent with Dictionary containing all required OAuth parameters (scope, client_id, grant_type, device information) +- For SSO and trusted device encryption flows, validate userDecryptionOptions object presence and structure in addition to standard token response properties + +## Continuation Context + + +Verify commands: +- grep -r 'using System.Text.Json' test/Identity.IntegrationTest/ --include='*Tests.cs' | wc -l +- grep -r 'JsonValueKind.Object' test/Identity.IntegrationTest/ --include='*Tests.cs' +- grep -r 'Assert.Equal.*error' test/Identity.IntegrationTest/RequestValidation/ --include='*Tests.cs' +- dotnet test test/Identity.IntegrationTest/ --filter 'FullyQualifiedName~ResourceOwnerPasswordValidatorTests|FullyQualifiedName~IdentityServerSsoTests' --no-build + +Accept when: +- System.Text.Json using statements are present in integration test files testing /connect/token endpoints +- JsonValueKind.Object assertions precede property extraction for complex JSON response objects +- Integration tests for authentication failures validate specific error message content with Assert.Equal +- All integration tests for OAuth token endpoints pass successfully with JSON assertion patterns in place + +## Enforcement + +- Verified by: Code review of integration test pull requests checking for System.Text.Json usage and JsonValueKind assertions +- Verified by: CI pipeline execution of Identity.IntegrationTest suite validating test pass rates +- Verified by: Static analysis or grep-based checks for consistent JSON assertion patterns in test files +- Violation handling: Pull requests introducing integration tests without proper JSON validation patterns are flagged in code review +- Violation handling: Test failures due to missing or incorrect JSON assertions block merge until corrected +- Violation handling: Periodic audit of integration test files to identify inconsistent JSON assertion patterns for refactoring +- Exception process: Exceptions for alternative JSON validation approaches require architectural review and documentation of rationale +- Exception process: Tests validating non-standard response formats may use alternative parsing strategies with approval from test infrastructure owners +- Exception process: Legacy tests may temporarily deviate from pattern during migration period with documented technical debt tracking \ No newline at end of file diff --git a/docs/adr/e334b687-3e75-4f83-9416-0376bf123735-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-requirements-enforced.md b/docs/adr/e334b687-3e75-4f83-9416-0376bf123735-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-requirements-enforced.md new file mode 100644 index 000000000000..ef0abb397f5e --- /dev/null +++ b/docs/adr/e334b687-3e75-4f83-9416-0376bf123735-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-authorization-requirements-enforced.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Authorization Requirements Enforced + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. SHOULD: Authorization requirements SHOULD be enforced declaratively using [Authorize] attributes where possible, falling back to imperative checks for complex scenarios + +## Policy Block + +- SHOULD Authorization requirements SHOULD be enforced declaratively using [Authorize] attributes where possible, falling back to imperative checks for complex scenarios + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/e4b39357-d928-4adb-b122-794be886cc4b-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-read-only-collection.md b/docs/adr/e4b39357-d928-4adb-b122-794be886cc4b-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-read-only-collection.md new file mode 100644 index 000000000000..152d3e9f71b3 --- /dev/null +++ b/docs/adr/e4b39357-d928-4adb-b122-794be886cc4b-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-read-only-collection.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Read Only Collection + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. SHOULD: Read-only collection access SHOULD be preserved during user updates by combining editable collections with readonly collections the updating user cannot modify + +## Policy Block + +- SHOULD Read-only collection access SHOULD be preserved during user updates by combining editable collections with readonly collections the updating user cannot modify + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/e4cab412-0466-4df2-9c64-80bb2e9e897c-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-operations-involving.md b/docs/adr/e4cab412-0466-4df2-9c64-80bb2e9e897c-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-operations-involving.md new file mode 100644 index 000000000000..5c562dc2a2b1 --- /dev/null +++ b/docs/adr/e4cab412-0466-4df2-9c64-80bb2e9e897c-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-cryptographic-operations-involving.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Cryptographic Operations Involving + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. MUST: Cryptographic operations involving SymmetricCryptoKey and RSA key material MUST validate inputs before processing + +## Policy Block + +- MUST Cryptographic operations involving SymmetricCryptoKey and RSA key material MUST validate inputs before processing + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/e6596a48-53e0-4b58-9297-172d935261dd-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-async.md b/docs/adr/e6596a48-53e0-4b58-9297-172d935261dd-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-async.md new file mode 100644 index 000000000000..caed46249440 --- /dev/null +++ b/docs/adr/e6596a48-53e0-4b58-9297-172d935261dd-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-async.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Use Async + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. MUST: Tests MUST use async/await patterns when invoking query methods that return Task types to properly test asynchronous coordination logic + +## Policy Block + +- MUST Tests MUST use async/await patterns when invoking query methods that return Task types to properly test asynchronous coordination logic + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/e782046c-a190-4db5-9ebc-3191004e3b34-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-controllers-use-iauthorizationservice.md b/docs/adr/e782046c-a190-4db5-9ebc-3191004e3b34-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-controllers-use-iauthorizationservice.md new file mode 100644 index 000000000000..afbaf74ea9c4 --- /dev/null +++ b/docs/adr/e782046c-a190-4db5-9ebc-3191004e3b34-enforce-authorization-checks-before-domain-validation-in-organization-user-operations-controllers-use-iauthorizationservice.md @@ -0,0 +1,124 @@ +# Enforce Authorization Checks Before Domain Validation in Organization User Operations: Controllers Use Iauthorizationservice + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The OrganizationUsersController in Bit.Api.AdminConsole handles multi-tenant organization user management operations requiring fine-grained authorization checks before domain validation +- Authorization decisions use IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) to evaluate user permissions against organization resources +- Domain validation occurs after authorization checks to prevent information disclosure through error messages, throwing NotFoundException when authorization fails rather than UnauthorizedException +- The controller coordinates authorization across multiple entity types (OrganizationUser, Collection, Group) with varying access control rules based on organization abilities and user roles +- Authorization enforcement points are distributed across HTTP endpoints (HttpGet, HttpPost, HttpPut, HttpDelete) using both attribute-based ([Authorize]) and imperative authorization patterns + +## Problem Statement + +Multi-tenant organization user management operations must prevent unauthorized access and information disclosure while maintaining usable error responses. Without consistent authorization-before-validation ordering, systems risk leaking entity existence through different error types, enabling enumeration attacks and violating least-privilege principles. + +## Decision + +1. MUST: Controllers MUST use IAuthorizationService.AuthorizeAsync with typed requirements rather than role-based checks for authorization decisions + +## Policy Block + +- MUST Controllers MUST use IAuthorizationService.AuthorizeAsync with typed requirements rather than role-based checks for authorization decisions + +In scope: +- All HTTP endpoints in controllers under Bit.Api.AdminConsole.Controllers managing organization users, collections, and groups +- Operations modifying user access to collections or groups within multi-tenant organizations +- Bulk operations affecting multiple organization users or collections simultaneously +- Self-service operations where users modify their own organization membership or permissions + +Out of scope: +- Authentication mechanisms and identity provider integration +- Authorization decisions within business logic layers below the controller +- Authorization for non-organization resources (vaults, ciphers, folders) +- Rate limiting and abuse prevention mechanisms + +Exceptions: +- EXC-001: Public invite acceptance endpoints where the user is not yet authenticated to the organization +- EXC-002: System-initiated operations with elevated service account privileges + +## Rationale + +- The evidence shows consistent use of IAuthorizationService with custom requirements (ManageUsersRequirement, BulkCollectionOperations.ModifyUserAccess) coordinating authorization decisions before domain validation in OrganizationUsersController +- Throwing NotFoundException on authorization failure prevents attackers from distinguishing between non-existent resources and unauthorized access, reducing information disclosure risk in multi-tenant environments +- The pattern of checking authorization against collections before modifying user access ensures that users cannot grant permissions they themselves do not possess, maintaining least-privilege principles +- Separating authorization enforcement (IAuthorizationService) from domain validation logic enables consistent security policy application across multiple endpoints while keeping business logic focused on domain rules + +## Consequences + +Positive: +- Prevents information disclosure attacks by returning uniform NotFoundException responses for both missing and unauthorized resources +- Enables fine-grained authorization policies through typed requirements (ManageUsersRequirement, BulkCollectionOperations) evaluated by centralized IAuthorizationService +- Maintains least-privilege by preventing users from granting themselves permissions to collections when organization policies restrict admin access +- Supports audit and compliance requirements through consistent authorization enforcement points across all organization user management operations + +Negative: +- Increases complexity of controller methods by requiring authorization checks before domain validation, adding multiple conditional branches +- May degrade debuggability as NotFoundException masks the underlying authorization failure reason in logs and error responses +- Requires careful coordination between authorization checks and domain validation to avoid time-of-check-time-of-use vulnerabilities in concurrent operations +- Complicates testing as authorization behavior must be mocked or configured for each test scenario involving organization user operations + +## Alternatives + +- Return 403 Forbidden for authorization failures instead of 404 NotFoundException (rejected) + Rejected because: Leaks information about resource existence to unauthorized users, enabling enumeration attacks in multi-tenant systems + When valid: Single-tenant systems where all authenticated users have visibility into resource existence +- Perform authorization checks in business logic layer instead of controller (rejected) + Rejected because: Separates authorization enforcement from HTTP context and user principal, complicating audit logging and making it harder to apply consistent policies across endpoints + When valid: Systems with complex authorization rules requiring domain context not available at controller layer +- Use role-based authorization attributes ([Authorize(Roles="Admin")]) instead of requirement-based authorization (rejected) + Rejected because: Lacks flexibility for resource-specific authorization (e.g., BulkCollectionOperations.ModifyUserAccess) and cannot express complex policies involving organization abilities + When valid: Simple applications with coarse-grained role hierarchies and no resource-level authorization needs + +## Risks + +- Time-of-check-time-of-use vulnerabilities if authorization checks and domain operations are not atomic, allowing concurrent modifications to bypass authorization + Mitigation: Use database transactions spanning authorization checks and domain operations, or implement optimistic concurrency control with version checks + Owner: Security team and backend engineering team +- Inconsistent authorization enforcement if some endpoints bypass IAuthorizationService and implement custom authorization logic + Mitigation: Establish code review guidelines requiring IAuthorizationService usage, implement static analysis rules to detect authorization bypasses + Owner: Security team and platform engineering team +- Performance degradation from multiple authorization checks per request, especially in bulk operations affecting many collections or users + Mitigation: Implement authorization result caching within request scope, batch authorization checks where possible, monitor authorization check latency + Owner: Performance engineering team + +## Implementation Notes + +- Inject IAuthorizationService into controllers and call AuthorizeAsync with typed requirements (ManageUsersRequirement, BulkCollectionOperations) before domain validation +- Use [Authorize] attributes for simple authorization checks, falling back to imperative AuthorizeAsync calls when authorization depends on loaded entities +- Throw NotFoundException (not UnauthorizedException or ForbiddenException) when authorization fails to prevent information disclosure about resource existence +- For operations modifying collection access, load all affected collections and verify ModifyUserAccess authorization before applying changes +- Preserve readonly collection access during updates by filtering collections the updating user cannot modify and combining them with editable collections +- Check organization abilities (AllowAdminAccessToAllCollectionItems) before allowing self-modification operations that could escalate privileges + +## Continuation Context + + +Verify commands: +- grep -r 'AuthorizeAsync.*BulkCollectionOperations' src/Api/AdminConsole/Controllers/ | wc -l +- grep -r 'throw new NotFoundException()' src/Api/AdminConsole/Controllers/OrganizationUsersController.cs | grep -A5 -B5 'AuthorizeAsync' | wc -l +- grep -r 'IAuthorizationService' src/Api/AdminConsole/Controllers/ --include='*Controller.cs' | wc -l + +Accept when: +- All organization user management endpoints perform authorization checks using IAuthorizationService before domain validation logic +- Failed authorization checks consistently throw NotFoundException rather than UnauthorizedException or ForbiddenException +- Collection access modification operations verify BulkCollectionOperations.ModifyUserAccess for all affected collections before applying changes +- Static analysis or code review confirms no authorization bypasses exist in organization user management controllers + +## Enforcement + +- Verified by: Code review checklist requiring IAuthorizationService usage verification for all new organization user management endpoints +- Verified by: Static analysis rules detecting authorization bypasses or incorrect exception types on authorization failures +- Verified by: Integration tests verifying NotFoundException responses for unauthorized access attempts across all endpoints +- Verified by: Security testing including authorization bypass attempts and information disclosure tests +- Violation handling: Pull requests failing authorization pattern checks are blocked from merge until corrected +- Violation handling: Security team notified of authorization bypasses detected in production code for immediate remediation +- Violation handling: Violations discovered in security testing trigger incident response process and immediate patching +- Violation handling: Quarterly security audits review authorization enforcement consistency across all controllers +- Exception process: Exception requests must document specific endpoint, justification, alternative authorization mechanism, and security team approval +- Exception process: Security team reviews exception requests within 2 business days, requiring architecture review for system-level exceptions +- Exception process: Approved exceptions are documented in code comments with ticket references and expiration dates for review +- Exception process: All exceptions are reviewed quarterly and must be re-justified or remediated \ No newline at end of file diff --git a/docs/adr/e99923c1-abac-4b79-8b4a-16a0918ab5f9-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-requirement-classes.md b/docs/adr/e99923c1-abac-4b79-8b4a-16a0918ab5f9-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-requirement-classes.md new file mode 100644 index 000000000000..afeab2eafec3 --- /dev/null +++ b/docs/adr/e99923c1-abac-4b79-8b4a-16a0918ab5f9-standardize-authorization-model-using-attribute-based-requirements-on-controller-actions-authorization-requirement-classes.md @@ -0,0 +1,126 @@ +# Standardize Authorization Model Using Attribute-Based Requirements on Controller Actions: Authorization Requirement Classes + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all API controller implementations requiring authorization enforcement. + +## Context + +- The codebase contains multiple ASP.NET Core API controllers (OrganizationInviteLinksController, HomeController, ProviderOrganizationsController, PoliciesController) that enforce authorization using the Microsoft.AspNetCore.Authorization framework +- Authorization requirements are applied declaratively using [Authorize] attributes with generic type parameters specifying custom requirement classes (ManageUsersRequirement, ProviderUserRequirement, ProviderAdminRequirement, ManagePoliciesRequirement, OrgUserLinkedToUserIdRequirement) +- The pattern appears across 4 files with 78.97% confidence, indicating a consistent approach to authorization enforcement at the controller action level +- Controllers coordinate with domain services, repositories, and command/query handlers while enforcing authorization boundaries before executing business logic +- The authorization model separates permission checking from business logic, enabling centralized policy enforcement and consistent security boundaries across API endpoints + +## Problem Statement + +API controllers require a consistent, declarative mechanism to enforce authorization policies that can express complex organizational permissions (manage users, manage policies, provider admin rights) while maintaining separation between authorization logic and business logic, and ensuring that authorization checks are applied uniformly across all protected endpoints without requiring manual permission validation in each action method. + +## Decision + +1. MUST: Authorization requirement classes MUST be defined in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements) + +## Policy Block + +- MUST Authorization requirement classes MUST be defined in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization, Bit.Api.AdminConsole.Authorization.Requirements, Bit.Api.AdminConsole.Authorization.Providers.Requirements) + +In scope: +- All ASP.NET Core API controllers in the Api and AdminConsole projects +- HTTP action methods (GET, POST, PUT, DELETE) that access protected organizational or user resources +- Controllers that enforce organizational permissions (ManageUsers, ManagePolicies, ProviderAdmin, ProviderUser) +- Endpoints requiring user-specific or organization-specific authorization + +Out of scope: +- Public endpoints explicitly marked with [AllowAnonymous] +- Health check or diagnostic endpoints that do not access protected resources +- Authentication endpoints (login, registration) that establish identity rather than enforce permissions +- Internal service-to-service communication that uses alternative authorization mechanisms + +Exceptions: +- EXC-001: Token-based validation is used for invite links or temporary access grants where traditional user authentication is not yet established +- EXC-002: Deprecated endpoints maintain backward compatibility during migration periods + +## Rationale + +- The evidence shows consistent use of generic [Authorize] attributes across 4 controller files, indicating an established pattern for declarative authorization that separates security concerns from business logic +- Custom requirement classes (ManageUsersRequirement, ManagePoliciesRequirement, ProviderAdminRequirement) enable fine-grained, domain-specific authorization policies that align with organizational permission models +- The pattern leverages ASP.NET Core's built-in authorization framework (Microsoft.AspNetCore.Authorization), reducing custom security code and benefiting from framework-level security guarantees +- Attribute-based authorization provides compile-time visibility of security requirements and enables centralized policy enforcement through authorization handlers, improving auditability and reducing the risk of missing authorization checks + +## Consequences + +Positive: +- Centralized authorization logic in dedicated requirement classes and handlers reduces code duplication and ensures consistent permission enforcement across all API endpoints +- Declarative authorization attributes make security requirements immediately visible in controller code, improving code readability and security audit efficiency +- Framework-level authorization integration enables automatic enforcement before action methods execute, preventing authorization bypass vulnerabilities +- Custom requirement classes enable domain-specific authorization logic that can express complex organizational hierarchies and permission models + +Negative: +- Generic type parameters in attributes ([Authorize]) may reduce discoverability for developers unfamiliar with the custom authorization framework +- Complex authorization scenarios requiring multiple checks may still need programmatic ICurrentContext validation within action methods, creating dual authorization patterns +- Custom requirement classes and handlers increase the initial learning curve and require additional infrastructure code compared to simple role-based authorization +- Authorization failures that throw NotFoundException for security reasons may complicate debugging and error handling for legitimate access issues + +## Alternatives + +- Use simple role-based authorization with [Authorize(Roles = "Admin")] attributes (rejected) + Rejected because: Role-based authorization cannot express the fine-grained organizational permissions required (ManageUsers, ManagePolicies, ProviderAdmin) and does not support the multi-tenant organizational hierarchy evident in the codebase + When valid: Simple applications with flat permission models and no organizational hierarchy +- Implement all authorization checks programmatically within action methods using ICurrentContext (rejected) + Rejected because: Programmatic checks are error-prone, easy to forget, and do not benefit from framework-level enforcement guarantees; the evidence shows ICurrentContext is used only for supplementary checks, not primary authorization + When valid: Complex authorization logic that cannot be expressed declaratively or requires runtime data not available during attribute evaluation +- Use policy-based authorization with string-based policy names [Authorize(Policy = "ManageUsers")] (rejected) + Rejected because: String-based policy names lack compile-time safety and type checking; the generic type parameter approach provides stronger coupling between controllers and requirement classes + When valid: Applications requiring dynamic policy registration or runtime policy composition + +## Risks + +- Developers may forget to apply [Authorize] attributes to new controller actions, creating unprotected endpoints + Mitigation: Implement automated static analysis to detect controller actions without authorization attributes; establish code review checklist requiring authorization verification + Owner: Security team and engineering team +- Complex authorization requirements may lead to inconsistent use of attribute-based vs. programmatic authorization checks + Mitigation: Document clear guidelines for when to use each approach; establish architectural patterns for common authorization scenarios + Owner: Architecture team +- Custom requirement classes may proliferate without clear naming conventions or organizational structure + Mitigation: Establish naming conventions (e.g., *Requirement suffix) and namespace organization (Authorization.Requirements); maintain a registry of available requirements + Owner: Engineering team + +## Implementation Notes + +- Define custom requirement classes in dedicated authorization namespaces (e.g., Bit.Api.AdminConsole.Authorization.Requirements) with clear naming that reflects the permission being enforced +- Implement corresponding authorization handlers that evaluate requirements against the current user context, organizational membership, and permission grants +- Use ICurrentContext for supplementary runtime checks when authorization depends on request parameters (e.g., validating organization ownership with _currentContext.OrganizationOwner(model.OrganizationId)) +- Throw NotFoundException rather than UnauthorizedAccessException when authorization fails to prevent information disclosure about resource existence +- Document each requirement class with clear descriptions of the permission it enforces and the organizational roles that satisfy it + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize<.*Requirement>\]" src/Api --include="*.cs" | wc -l +- grep -r "public.*Task.*IResult\|public.*Task<.*ResponseModel>" src/Api/AdminConsole/Controllers --include="*.cs" | grep -v "\[Authorize" | grep -v "\[AllowAnonymous" +- find src/Api -name "*Controller.cs" -exec grep -L "using Microsoft.AspNetCore.Authorization" {} \; + +Accept when: +- All protected controller actions include [Authorize] attributes with custom requirement classes +- No controller actions accessing protected resources lack authorization attributes unless explicitly marked [AllowAnonymous] +- All custom requirement classes are defined in dedicated authorization namespaces with consistent naming conventions +- Authorization failures consistently throw NotFoundException or UnauthorizedAccessException as appropriate + +## Enforcement + +- Verified by: Automated static analysis scanning for controller actions without authorization attributes +- Verified by: Code review checklist requiring verification of authorization attributes on all new controller actions +- Verified by: Security-focused integration tests validating that unauthorized requests receive appropriate 401/403/404 responses +- Verified by: Periodic security audits reviewing authorization requirement implementations and handler logic +- Violation handling: Static analysis failures block pull request merging until authorization attributes are added +- Violation handling: Code review process requires explicit justification for any [AllowAnonymous] usage +- Violation handling: Security team review required for any new custom requirement classes to ensure consistent authorization semantics +- Violation handling: Penetration testing findings related to missing authorization trigger immediate remediation and pattern review +- Exception process: Exceptions for public endpoints must be documented with [AllowAnonymous] attribute and justification in code comments +- Exception process: Temporary authorization bypasses for migration or backward compatibility require architecture team approval with documented sunset date +- Exception process: Alternative authorization mechanisms (token-based, service-to-service) require security team review and documentation of validation approach \ No newline at end of file diff --git a/docs/adr/eab0181a-1b33-4cfc-bfab-97f8aaf0ef10-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-dependency.md b/docs/adr/eab0181a-1b33-4cfc-bfab-97f8aaf0ef10-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-dependency.md new file mode 100644 index 000000000000..47ce1be33c79 --- /dev/null +++ b/docs/adr/eab0181a-1b33-4cfc-bfab-97f8aaf0ef10-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-use-dependency.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Use Dependency + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. MUST: Tests MUST use dependency injection providers (sutProvider) to supply mock implementations of repository interfaces (ISecretRepository, IServiceAccountRepository) to the system under test + +## Policy Block + +- MUST Tests MUST use dependency injection providers (sutProvider) to supply mock implementations of repository interfaces (ISecretRepository, IServiceAccountRepository) to the system under test + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/ecab59e9-ab15-4328-a38c-6ebe589b784d-use-structured-logging-with-contextual-parameters-for-external-service-failures-return-fallback-responses.md b/docs/adr/ecab59e9-ab15-4328-a38c-6ebe589b784d-use-structured-logging-with-contextual-parameters-for-external-service-failures-return-fallback-responses.md new file mode 100644 index 000000000000..4794c7edfabf --- /dev/null +++ b/docs/adr/ecab59e9-ab15-4328-a38c-6ebe589b784d-use-structured-logging-with-contextual-parameters-for-external-service-failures-return-fallback-responses.md @@ -0,0 +1,117 @@ +# Use Structured Logging with Contextual Parameters for External Service Failures: Return Fallback Responses + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Controllers in the Admin and AdminConsole namespaces integrate with external services (Stripe, version endpoints) where failures must be logged without blocking primary operations +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns that accept exception objects and contextual parameters +- Authorization-protected endpoints (using [Authorize] attributes and custom requirements like ProviderAdminRequirement) perform operations that may partially succeed, requiring detailed failure context +- External HTTP calls and third-party service integrations introduce failure modes that need diagnostic context (URIs, entity IDs) for operational troubleshooting + +## Problem Statement + +When controller methods interact with external services or perform multi-step operations involving third-party integrations, failures in non-critical paths (such as Stripe synchronization after database updates, or version check HTTP requests) must be logged with sufficient diagnostic context to enable troubleshooting without exposing the failure to end users or blocking the primary operation flow. + +## Decision + +1. MAY: Return fallback responses (e.g., '-' or error JSON) to clients when external service calls fail, with appropriate HTTP status codes for true errors + +## Policy Block + +- MAY Return fallback responses (e.g., '-' or error JSON) to clients when external service calls fail, with appropriate HTTP status codes for true errors + +In scope: +- Controller methods decorated with [Authorize] or custom authorization requirements +- Operations involving external HTTP clients (IHttpClientFactory usage) +- Third-party service integrations (Stripe, external APIs) +- Multi-step operations where partial success is acceptable + +Out of scope: +- Internal service method calls within the same application boundary +- Database operations that are critical to request success +- Validation failures that should propagate to the client +- Authentication/authorization failures + +Exceptions: +- EX-001: External service call is critical to the request and failure must propagate to the client + +## Rationale + +- The evidence shows consistent use of ILogger.LogError with exception objects and structured parameters ({ProviderId}, {RequestUri}) across ProvidersController and HomeController, indicating an established pattern for diagnostic logging +- External service failures (Stripe customer updates, version check HTTP requests) are caught and logged without blocking primary operations, enabling partial success patterns where database updates succeed even if synchronization fails +- Structured logging with named parameters enables log aggregation systems to index and query by entity IDs and URIs, improving operational troubleshooting capabilities +- The pattern appears in authorization-protected endpoints where audit trails and failure diagnostics are particularly important for security and compliance + +## Consequences + +Positive: +- Operational failures in external services are captured with diagnostic context without blocking user requests +- Structured log parameters enable efficient querying and correlation in log aggregation systems (e.g., searching all failures for a specific ProviderId) +- Exception objects preserve stack traces and inner exceptions for root cause analysis +- Partial success patterns allow critical operations (database updates) to complete even when non-critical synchronization fails + +Negative: +- Try-catch blocks around external calls add code complexity and nesting depth +- Logged errors may create alert fatigue if external services have frequent transient failures +- Partial success states require careful documentation to avoid confusion about system consistency +- Developers must remember to add structured parameters for each new external service integration + +## Alternatives + +- Propagate all external service exceptions to the client without logging (rejected) + Rejected because: Would block primary operations (database updates) when non-critical synchronization fails, degrading user experience and system availability + When valid: When external service call is truly critical to request success and partial completion is unacceptable +- Use unstructured string concatenation for log messages (rejected) + Rejected because: Prevents log aggregation systems from indexing and querying by entity IDs, URIs, and other contextual parameters, reducing operational effectiveness + When valid: Never recommended in modern observability practices +- Queue failed external operations for retry via background job (deferred) + Rejected because: Adds infrastructure complexity (queue, worker) but may be valuable for critical synchronization operations + When valid: When eventual consistency is required and immediate synchronization failure is unacceptable + +## Risks + +- Inconsistent application of structured logging parameters across different controllers and services + Mitigation: Establish code review checklist for external service integrations requiring structured logging with entity IDs and URIs + Owner: Engineering team +- Sensitive data (tokens, API keys) accidentally logged in exception messages or parameters + Mitigation: Use log scrubbing middleware and review exception messages for PII/secrets before logging; avoid logging request bodies + Owner: Security team +- Partial success states create data inconsistency between primary system and external services + Mitigation: Document expected consistency model; implement monitoring alerts for sustained synchronization failures; consider retry mechanisms for critical integrations + Owner: Operations team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controller classes +- Use named placeholders in log message templates that match parameter names (e.g., _logger.LogError(ex, 'Failed for {ProviderId}', providerId)) +- Wrap external service calls (IHttpClientFactory, third-party SDKs) in try-catch blocks when the operation is non-critical +- Include context about primary operation state in log messages (e.g., 'Database updated successfully' helps correlate partial success) +- Configure log aggregation to index structured parameters for querying (ProviderId, RequestUri, etc.) + +## Continuation Context + + +Verify commands: +- grep -r 'LogError.*{.*}' --include='*Controller.cs' src/ +- grep -r 'catch.*Exception.*LogError' --include='*.cs' src/Api src/Admin +- dotnet test --filter 'Category=Logging' --logger 'console;verbosity=detailed' + +Accept when: +- All controller methods with external service calls use ILogger.LogError with exception object and at least one structured parameter +- External service failures in non-critical paths are caught and logged without propagating to client +- Log messages include contextual parameters using named placeholders matching the structured logging pattern + +## Enforcement + +- Verified by: Code review checklist for controller changes involving external services +- Verified by: Static analysis rules detecting LogError calls without structured parameters +- Verified by: Integration test coverage for external service failure scenarios +- Violation handling: PR comments requesting addition of structured logging for external service calls +- Violation handling: Build warnings for LogError calls using string concatenation instead of structured parameters +- Violation handling: Post-incident reviews when operational troubleshooting is hindered by insufficient log context +- Exception process: Document in code comments why structured logging is not applicable +- Exception process: Obtain approval from team lead for exceptions to structured parameter requirements +- Exception process: Record exception rationale in ADR amendments or architecture decision log \ No newline at end of file diff --git a/docs/adr/ed1f3bfd-e75f-4a51-b083-1e9ff6c63c3f-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-functions-that.md b/docs/adr/ed1f3bfd-e75f-4a51-b083-1e9ff6c63c3f-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-functions-that.md new file mode 100644 index 000000000000..2c394e81240b --- /dev/null +++ b/docs/adr/ed1f3bfd-e75f-4a51-b083-1e9ff6c63c3f-adopt-ffi-safe-cryptographic-key-generation-with-memory-management-in-rust-sdk-ffi-functions-that.md @@ -0,0 +1,114 @@ +# Adopt FFI-Safe Cryptographic Key Generation with Memory Management in Rust SDK: Ffi Functions That + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary using c_char pointers and CString/CStr conversions +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations, requiring careful memory management across FFI boundaries to prevent leaks and use-after-free vulnerabilities +- Public API contracts are defined with explicit memory deallocation functions (free_c_string) to ensure calling code can safely release allocated resources +- The testing.mocking facet indicates test infrastructure for cipher and rsa_keys components, suggesting validation of cryptographic operations in isolation +- Input validation patterns are applied to cipher and rsa_keys operations to ensure secure handling of cryptographic material at the FFI boundary + +## Problem Statement + +Exposing cryptographic key generation through FFI boundaries introduces memory safety risks, including potential leaks, use-after-free errors, and improper handling of sensitive cryptographic material. Without standardized patterns for FFI-safe memory management and input validation, the SDK risks exposing vulnerabilities at the language boundary where Rust's safety guarantees do not automatically extend. + +## Decision + +1. MUST: FFI functions that allocate memory MUST provide corresponding deallocation functions (e.g., free_c_string) in the public API + +## Policy Block + +- MUST FFI functions that allocate memory MUST provide corresponding deallocation functions (e.g., free_c_string) in the public API + +In scope: +- All cryptographic key generation functions in util/RustSdk/rust/src/lib.rs +- FFI boundary functions that allocate or manipulate cryptographic material +- Memory management functions for C-allocated strings and cryptographic keys +- Input validation for cipher and RSA key operations + +Out of scope: +- Pure Rust cryptographic operations that do not cross FFI boundaries +- Internal cryptographic library implementations (bitwarden_crypto) +- Non-cryptographic FFI functions +- Platform-specific cryptographic backends + +## Rationale + +- The evidence shows explicit use of std::ffi types (c_char, CStr, CString) in util/RustSdk/rust/src/lib.rs, indicating a deliberate pattern for FFI-safe string handling across language boundaries +- The presence of free_c_string in public API contracts demonstrates awareness of memory management responsibilities at FFI boundaries, preventing resource leaks in calling code +- The use of RSA_POOL and bitwarden_crypto::SymmetricCryptoKey indicates centralized management of cryptographic resources, reducing the risk of improper key material handling +- Testing infrastructure for cipher and rsa_keys components (testing.mocking facet) provides validation that cryptographic operations behave correctly in isolation, supporting secure coding practices + +## Consequences + +Positive: +- Memory safety is maintained across FFI boundaries through explicit allocation/deallocation pairs, preventing leaks and use-after-free errors +- Cryptographic key material is handled through validated, type-safe interfaces that leverage Rust's safety guarantees where possible +- Centralized resource management (RSA_POOL) provides consistent lifecycle handling for expensive cryptographic resources +- Test mocks enable validation of cryptographic operations without requiring full integration, improving test reliability and security verification + +Negative: +- FFI boundary overhead introduces additional complexity in API design, requiring paired allocation/deallocation functions for each resource type +- Calling code must correctly invoke deallocation functions, placing memory safety burden on consumers of the API +- CString/CStr conversions add runtime overhead and potential panic points if null bytes are present in strings +- Testing infrastructure requires maintenance of mock implementations that must stay synchronized with production cryptographic behavior + +## Alternatives + +- Use opaque handle-based API with internal reference counting instead of raw C string pointers (rejected) + Rejected because: Would require more complex FFI infrastructure and does not align with the observed pattern of direct c_char pointer usage in the evidence + When valid: When building a new FFI layer from scratch with more complex resource lifecycle requirements +- Expose cryptographic operations only through higher-level language bindings (Python, JavaScript) rather than C FFI (rejected) + Rejected because: Does not address the existing C FFI requirement evidenced by the current implementation in util/RustSdk/rust/src/lib.rs + When valid: When C interoperability is not a requirement and all consumers can use higher-level language runtimes +- Use automatic memory management through garbage collection or reference counting at FFI boundary (rejected) + Rejected because: C FFI does not provide automatic memory management, and the evidence shows explicit free_c_string function for manual deallocation + When valid: When targeting managed runtime environments that provide automatic memory management across FFI + +## Risks + +- Calling code may fail to invoke free_c_string, causing memory leaks in long-running processes + Mitigation: Document memory management requirements clearly in API documentation and provide examples showing correct allocation/deallocation patterns + Owner: SDK engineering team +- CString conversions may panic on null bytes in input strings, causing undefined behavior at FFI boundary + Mitigation: Implement input validation that returns error codes rather than panicking, and document valid input constraints + Owner: SDK engineering team +- Test mocks may diverge from production cryptographic behavior, leading to false confidence in security properties + Mitigation: Maintain integration tests that exercise real cryptographic implementations alongside unit tests with mocks, and regularly audit mock behavior against production + Owner: Security and QA teams + +## Implementation Notes + +- All new FFI functions that allocate memory must provide a corresponding free_* function and document the caller's responsibility to invoke it +- Use std::panic::catch_unwind around CString conversions to prevent panics from crossing FFI boundaries, returning error codes instead +- Validate all input parameters at the FFI boundary before passing to internal cryptographic functions, checking for null pointers and invalid lengths +- Ensure test mocks for cipher and rsa_keys components cover edge cases including invalid inputs, memory exhaustion, and concurrent access patterns + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'c_char' +- grep -c 'free_c_string' util/RustSdk/rust/src/lib.rs +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions for key generation use c_char pointers with CString/CStr conversions +- A free_c_string function exists in the public API for memory deallocation +- std::ffi types are imported and used for FFI boundary operations + +## Enforcement + +- Verified by: Code review of all FFI boundary functions to verify paired allocation/deallocation +- Verified by: Static analysis to detect CString conversions without corresponding error handling +- Verified by: Memory leak detection in CI using valgrind or similar tools on FFI integration tests +- Violation handling: FFI functions without paired deallocation functions must be rejected in code review +- Violation handling: Memory leaks detected in CI must block merge until resolved +- Violation handling: Panics at FFI boundaries must be converted to error returns before production deployment +- Exception process: Exceptions for FFI patterns must be reviewed by security team and SDK maintainers +- Exception process: Alternative memory management approaches must demonstrate equivalent safety properties +- Exception process: All exceptions must be documented in code comments with rationale and approval record \ No newline at end of file diff --git a/docs/adr/eeeb0b67-297d-4d5d-be90-ca0ff7011f0a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-query.md b/docs/adr/eeeb0b67-297d-4d5d-be90-ca0ff7011f0a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-query.md new file mode 100644 index 000000000000..a37d5e78080f --- /dev/null +++ b/docs/adr/eeeb0b67-297d-4d5d-be90-ca0ff7011f0a-isolate-system-under-test-from-external-dependencies-via-query-interface-abstraction-tests-verify-query.md @@ -0,0 +1,113 @@ +# Isolate System Under Test from External Dependencies via Query Interface Abstraction: Tests Verify Query + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Bitwarden Commercial.Core.Test suite tests query classes in the SecretsManager domain that coordinate access policy updates and secret synchronization operations +- Query classes depend on external repository interfaces (ISecretRepository, IServiceAccountRepository) that require isolation during unit testing to verify query logic independently +- Test classes use sutProvider pattern to inject mock dependencies, enabling verification of query behavior without database or external service dependencies +- The codebase separates query orchestration logic from data access, requiring test strategies that validate coordination behavior through interface boundaries + +## Problem Statement + +Unit tests for query classes that orchestrate complex access policy and secret management operations must verify coordination logic, operation classification (Create/Update/Delete), and conditional branching without coupling to concrete repository implementations or external data stores. Without interface-based isolation, tests become integration tests that depend on database state, increasing execution time and reducing determinism. + +## Decision + +1. MUST: Tests MUST verify query coordination behavior by asserting on returned data structures (result.ProjectGrantedPolicyUpdates, result.ServiceAccountAccessPolicyUpdates) rather than mocking internal method calls + +## Policy Block + +- MUST Tests MUST verify query coordination behavior by asserting on returned data structures (result.ProjectGrantedPolicyUpdates, result.ServiceAccountAccessPolicyUpdates) rather than mocking internal method calls + +In scope: +- Unit tests for query classes in Bit.Commercial.Core.SecretsManager.Queries namespace +- Tests that verify coordination logic for access policy updates (ServiceAccountGrantedPolicyUpdatesQuery, ProjectServiceAccountsAccessPoliciesUpdatesQuery) +- Tests that verify secret synchronization queries (SecretsSyncQuery) +- Query classes that depend on repository interfaces from Bit.Core.SecretsManager.Repositories + +Out of scope: +- Integration tests that require actual database connections +- Repository implementation tests that verify data access layer behavior +- End-to-end tests that exercise full request pipelines +- Tests for entity classes or data models that have no external dependencies + +## Rationale + +- The evidence shows consistent use of sutProvider.Sut.GetAsync(data) pattern across three test files, demonstrating interface-based isolation where the system under test is accessed only through its public contract +- Mock verification patterns (Received, DidNotReceiveWithAnyArgs) confirm that tests validate external boundary interactions without requiring concrete implementations +- Operation classification assertions (AccessPolicyOperation.Create/Update/Delete) prove that tests focus on query coordination logic rather than data persistence mechanics +- The pattern enables fast, deterministic unit tests that verify complex conditional logic (HasChanges, revision date comparisons, policy diff calculations) independently of external systems + +## Consequences + +Positive: +- Unit tests execute quickly without database or external service dependencies, enabling rapid feedback during development +- Query coordination logic can be verified independently, isolating failures to specific components rather than integration points +- Test scenarios can cover edge cases (empty state, missing entities, concurrent updates) that are difficult to reproduce with real dependencies +- Mock verification provides explicit documentation of expected repository interface contracts and parameter passing + +Negative: +- Tests do not verify actual repository implementation behavior or SQL query correctness, requiring separate integration test coverage +- Mock setup overhead increases test code volume and maintenance burden when repository interfaces change +- Over-reliance on mocking can lead to tests that pass but fail in production if mock behavior diverges from real implementations +- Complex mock verification logic (Arg.Is predicates, Received counts) can obscure test intent and make failures harder to diagnose + +## Alternatives + +- Use in-memory database implementations for repository interfaces during testing (rejected) + Rejected because: In-memory databases blur the line between unit and integration tests, increase test execution time, and introduce database-specific behavior that complicates test setup and teardown + When valid: Valid for integration tests that verify end-to-end query execution including SQL generation and result mapping +- Test query classes by directly invoking internal methods and inspecting private state (rejected) + Rejected because: Testing internal implementation details couples tests to refactorable code structure and violates encapsulation, making tests brittle to internal changes + When valid: Valid only when debugging specific internal logic issues, not for standard test coverage +- Use test doubles (hand-written fakes) instead of mocking frameworks for repository interfaces (deferred) + When valid: Valid when repository interfaces stabilize and reusable test doubles can reduce mock setup duplication across test suites + +## Risks + +- Mock behavior diverges from actual repository implementations, causing tests to pass while production code fails + Mitigation: Maintain integration test suite that exercises query classes with real repository implementations; review repository interface changes for impact on existing mocks + Owner: Engineering team +- Complex mock verification logic becomes difficult to maintain as repository interfaces evolve + Mitigation: Extract common mock setup patterns into test helper methods; document expected repository contracts in interface documentation + Owner: Engineering team +- Over-mocking leads to tests that verify mock interactions rather than meaningful business logic + Mitigation: Focus assertions on query result correctness (operation types, counts, data integrity) rather than exhaustive mock call verification + Owner: Engineering team + +## Implementation Notes + +- Use sutProvider pattern consistently across test classes to inject mock repository dependencies into query constructors +- Structure test methods to follow Arrange-Act-Assert pattern: setup mock data, invoke sutProvider.Sut.GetAsync, assert on result properties +- Name test methods descriptively to indicate scenario and expected outcome (e.g., GetAsync_NoCurrentGrantedPolicies_ReturnsAllCreates) +- Verify critical repository interactions using Received() assertions, but prioritize result correctness over exhaustive call verification +- Cover both happy path scenarios (successful coordination) and error scenarios (NotFoundException for missing entities) in test suites + +## Continuation Context + + +Verify commands: +- grep -r 'sutProvider.Sut.GetAsync' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- grep -r 'Assert.Equal.*Operation' bitwarden_license/test/Commercial.Core.Test/SecretsManager/Queries/ | wc -l +- dotnet test --filter 'FullyQualifiedName~Commercial.Core.Test.SecretsManager.Queries' --no-build + +Accept when: +- Query test files contain sutProvider.Sut.GetAsync invocations that access system under test through public interface +- Test assertions verify operation classification (AccessPolicyOperation enum values) in query results +- All query unit tests pass without requiring database connections or external service dependencies + +## Enforcement + +- Verified by: Code review verification that new query test classes follow sutProvider pattern and mock repository dependencies +- Verified by: CI pipeline execution of unit test suite with no database connection configuration +- Verified by: Static analysis to detect direct repository instantiation in test code rather than dependency injection +- Violation handling: Pull requests that introduce query tests with database dependencies are rejected during code review +- Violation handling: CI failures on unit test suite indicate violation of isolation principles and block merge +- Violation handling: Tests that exceed execution time thresholds (>100ms per test) are flagged for review of external dependencies +- Exception process: Integration tests that intentionally use real repositories must be placed in separate test projects with explicit naming (e.g., Commercial.Core.IntegrationTest) +- Exception process: Exception requests must document why interface-based isolation is insufficient for the specific test scenario +- Exception process: Architecture review approval required for exceptions that introduce external dependencies in unit test projects \ No newline at end of file diff --git a/docs/adr/ef0e6a8b-31a8-4d14-8127-dda7d12de886-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-integration-tests-use.md b/docs/adr/ef0e6a8b-31a8-4d14-8127-dda7d12de886-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-integration-tests-use.md new file mode 100644 index 000000000000..2c7f2cafb18a --- /dev/null +++ b/docs/adr/ef0e6a8b-31a8-4d14-8127-dda7d12de886-adopt-asp-net-core-iresult-pattern-for-http-response-abstraction-integration-tests-use.md @@ -0,0 +1,116 @@ +# Adopt ASP.NET Core IResult Pattern for HTTP Response Abstraction: Integration Tests Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- ASP.NET Core provides the IResult interface family (IResult, IStatusCodeHttpResult, IContentTypeHttpResult, IValueHttpResult) as a standardized abstraction for HTTP responses in minimal APIs and endpoint handlers +- The codebase implements custom result types (BitwardenValidationProblemResult) that wrap framework-provided results (ProblemHttpResult) while maintaining interface compatibility +- Integration tests demonstrate HTTP endpoint interaction patterns using Server.GetAsync, Server.PostAsync, Server.PutAsync, and Server.PatchAsync methods with HttpContext manipulation +- The pattern enables type-safe response composition with explicit status codes, content types, and value contracts without direct HttpContext manipulation in business logic + +## Problem Statement + +HTTP response handling in ASP.NET Core applications requires a consistent abstraction that decouples business logic from HttpContext details while maintaining type safety, testability, and framework compatibility across minimal APIs and MVC endpoints. + +## Decision + +1. MUST: Integration tests MUST use Server HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) rather than direct HttpContext construction + +## Policy Block + +- MUST Integration tests MUST use Server HTTP methods (GetAsync, PostAsync, PutAsync, PatchAsync) rather than direct HttpContext construction + +In scope: +- ASP.NET Core minimal API endpoints +- MVC controller action results +- Custom HTTP result types wrapping framework results +- Integration test HTTP client interactions + +Out of scope: +- Direct HttpResponse.WriteAsync calls in middleware +- SignalR hub method returns +- gRPC service implementations +- Background service HTTP clients + +Exceptions: +- EXC-001: Middleware components require direct HttpContext.Response manipulation for streaming or low-level protocol handling + +## Rationale + +- The IResult pattern provides a framework-native abstraction that separates response intent from execution, enabling better testability and composition +- Evidence shows custom result types (BitwardenValidationProblemResult) wrapping framework results (ProblemHttpResult) while maintaining full interface compatibility through delegation +- Integration test patterns demonstrate Server-based HTTP methods as the standard approach for endpoint testing, avoiding direct HttpContext construction +- The pattern supports both minimal APIs and MVC endpoints through a unified interface contract, reducing framework coupling in business logic + +## Consequences + +Positive: +- Type-safe HTTP response composition with compile-time verification of status codes, content types, and response values +- Improved testability through result inspection without executing HttpContext writes +- Framework-agnostic business logic that returns result objects rather than manipulating HttpContext directly +- Consistent integration testing patterns using Server HTTP methods across all endpoint types + +Negative: +- Additional abstraction layer increases cognitive overhead for developers unfamiliar with IResult pattern +- Custom result wrappers require boilerplate delegation code for each interface member +- Integration tests using Server methods may have higher setup cost compared to unit testing result objects directly +- Framework version coupling as IResult interface family evolves across ASP.NET Core releases + +## Alternatives + +- Direct HttpContext.Response manipulation in endpoint handlers (rejected) + Rejected because: Couples business logic to HttpContext, reduces testability, and prevents result composition before execution + When valid: Low-level middleware or protocol handlers requiring streaming or connection-level control +- ActionResult exclusively for all endpoints (rejected) + Rejected because: Ties implementation to MVC framework, incompatible with minimal APIs, and provides less granular interface contracts + When valid: MVC-only applications not using minimal APIs +- Custom response DTO pattern with manual serialization (rejected) + Rejected because: Requires reimplementing framework serialization, status code mapping, and content negotiation logic + When valid: Non-HTTP transport layers or custom binary protocols + +## Risks + +- Framework interface changes in future ASP.NET Core versions may break custom result implementations + Mitigation: Pin to stable ASP.NET Core LTS versions and test custom results against preview releases during upgrade planning + Owner: Platform Engineering Team +- Developers may bypass IResult pattern and use HttpContext.Response directly, fragmenting response handling approaches + Mitigation: Enforce through code review, static analysis rules, and architectural fitness functions in CI pipeline + Owner: Engineering Team +- Complex result wrapper hierarchies may introduce performance overhead through excessive delegation + Mitigation: Profile endpoint response times and limit wrapper depth to single-level delegation as shown in evidence + Owner: Performance Engineering Team + +## Implementation Notes + +- Implement custom result types as sealed classes wrapping framework results with internal constructors to control instantiation +- Use readonly fields for inner result storage and delegate all interface members to the wrapped instance +- Expose factory methods or extension methods for creating custom results rather than public constructors +- In integration tests, use Server.GetAsync/PostAsync/PutAsync/PatchAsync with lambda expressions for HttpContext configuration (headers, query strings) + +## Continuation Context + + +Verify commands: +- grep -r 'IResult\|IStatusCodeHttpResult\|IContentTypeHttpResult\|IValueHttpResult' --include='*.cs' src/ +- grep -r 'ExecuteAsync(HttpContext' --include='*.cs' src/ | grep -v 'HttpContext.Response.WriteAsync' +- grep -r 'Server\.GetAsync\|Server\.PostAsync\|Server\.PutAsync\|Server\.PatchAsync' --include='*.cs' test/ + +Accept when: +- All custom HTTP result types implement IResult and delegate ExecuteAsync to inner framework results +- Integration tests use Server HTTP methods rather than constructing HttpContext instances directly +- No direct HttpContext.Response manipulation exists in endpoint handlers outside approved middleware exceptions + +## Enforcement + +- Verified by: CI pipeline static analysis scanning for IResult interface implementation in result types +- Verified by: Code review checklist verification of ExecuteAsync delegation patterns +- Verified by: Integration test pattern validation ensuring Server method usage +- Violation handling: CI build warnings for result types not implementing IResult interface +- Violation handling: Code review rejection for direct HttpContext.Response usage in endpoint handlers +- Violation handling: Architecture review required for new result wrapper types +- Exception process: Submit exception request documenting technical rationale and alternative approaches considered +- Exception process: Architecture review board evaluates against middleware and protocol handler criteria +- Exception process: Approved exceptions documented in code comments with ADR reference \ No newline at end of file diff --git a/docs/adr/ef9da943-1527-4e31-a94f-b20de8163e9c-enforce-authorization-via-policy-based-configuration-in-scim-services-authentication-schemes-configured.md b/docs/adr/ef9da943-1527-4e31-a94f-b20de8163e9c-enforce-authorization-via-policy-based-configuration-in-scim-services-authentication-schemes-configured.md new file mode 100644 index 000000000000..df18321ebc54 --- /dev/null +++ b/docs/adr/ef9da943-1527-4e31-a94f-b20de8163e9c-enforce-authorization-via-policy-based-configuration-in-scim-services-authentication-schemes-configured.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authentication Schemes Configured + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. MUST: Authentication schemes MUST be configured before authorization policies are defined + +## Policy Block + +- MUST Authentication schemes MUST be configured before authorization policies are defined + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/f0570cf5-0f1d-4069-81c2-d602ba323070-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-boundary-validation.md b/docs/adr/f0570cf5-0f1d-4069-81c2-d602ba323070-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-boundary-validation.md new file mode 100644 index 000000000000..e59cd54b9f45 --- /dev/null +++ b/docs/adr/f0570cf5-0f1d-4069-81c2-d602ba323070-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-ffi-boundary-validation.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Ffi Boundary Validation + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. SHOULD: FFI boundary validation SHOULD occur before any cryptographic operations (cipher, rsa_keys, key generation) to prevent invalid data from reaching security-critical code paths + +## Policy Block + +- SHOULD FFI boundary validation SHOULD occur before any cryptographic operations (cipher, rsa_keys, key generation) to prevent invalid data from reaching security-critical code paths + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/f0941089-2e5d-43c2-8f5a-52162d5a565e-enforce-authorization-via-policy-based-configuration-in-scim-services-test-environments-use.md b/docs/adr/f0941089-2e5d-43c2-8f5a-52162d5a565e-enforce-authorization-via-policy-based-configuration-in-scim-services-test-environments-use.md new file mode 100644 index 000000000000..090e836358fc --- /dev/null +++ b/docs/adr/f0941089-2e5d-43c2-8f5a-52162d5a565e-enforce-authorization-via-policy-based-configuration-in-scim-services-test-environments-use.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Test Environments Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. SHOULD: Test environments SHOULD use simplified authorization policies with RequireAssertion for integration testing scenarios + +## Policy Block + +- SHOULD Test environments SHOULD use simplified authorization policies with RequireAssertion for integration testing scenarios + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/f10e50f9-1793-4078-bf2c-f87b82a11333-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-implementations-expose.md b/docs/adr/f10e50f9-1793-4078-bf2c-f87b82a11333-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-implementations-expose.md new file mode 100644 index 000000000000..c8f493dfae11 --- /dev/null +++ b/docs/adr/f10e50f9-1793-4078-bf2c-f87b82a11333-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-cache-implementations-expose.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Cache Implementations Expose + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. SHOULD: Cache implementations SHOULD expose the IDistributedCache interface for compatibility with standard ASP.NET Core caching patterns + +## Policy Block + +- SHOULD Cache implementations SHOULD expose the IDistributedCache interface for compatibility with standard ASP.NET Core caching patterns + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/f25d68ac-56d9-4222-93c1-b739d5abcf7e-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-middleware-added.md b/docs/adr/f25d68ac-56d9-4222-93c1-b739d5abcf7e-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-middleware-added.md new file mode 100644 index 000000000000..14c63eecadee --- /dev/null +++ b/docs/adr/f25d68ac-56d9-4222-93c1-b739d5abcf7e-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-authorization-middleware-added.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Authorization Middleware Added + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MUST: Authorization middleware MUST be added to the request pipeline via app.UseAuthorization() after authentication middleware + +## Policy Block + +- MUST Authorization middleware MUST be added to the request pipeline via app.UseAuthorization() after authentication middleware + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/f2603862-ba99-4ae7-bc7e-0252d4ad11ab-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-middleware-registered.md b/docs/adr/f2603862-ba99-4ae7-bc7e-0252d4ad11ab-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-middleware-registered.md new file mode 100644 index 000000000000..d6016069a570 --- /dev/null +++ b/docs/adr/f2603862-ba99-4ae7-bc7e-0252d4ad11ab-adopt-api-key-authentication-scheme-for-scim-service-endpoints-authentication-middleware-registered.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Authentication Middleware Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. SHOULD: Authentication middleware SHOULD be registered before authorization middleware in the ASP.NET Core pipeline using UseAuthentication followed by UseAuthorization + +## Policy Block + +- SHOULD Authentication middleware SHOULD be registered before authorization middleware in the ASP.NET Core pipeline using UseAuthentication followed by UseAuthorization + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/f2ec3be2-47e8-4626-9d21-f6a29049c4f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-modules-use.md b/docs/adr/f2ec3be2-47e8-4626-9d21-f6a29049c4f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-modules-use.md new file mode 100644 index 000000000000..afc94ed14497 --- /dev/null +++ b/docs/adr/f2ec3be2-47e8-4626-9d21-f6a29049c4f7-validate-ffi-input-using-rust-type-system-and-c-string-conversions-ffi-modules-use.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Ffi Modules Use + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. SHOULD: FFI modules SHOULD use std::collections::HashSet or similar structures to track allocated resources requiring cleanup via free_c_string + +## Policy Block + +- SHOULD FFI modules SHOULD use std::collections::HashSet or similar structures to track allocated resources requiring cleanup via free_c_string + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/f3f0b5bc-743a-4b38-b3c9-7f1376973b7a-validate-ffi-input-using-rust-type-system-and-c-string-conversions-test-suites-include.md b/docs/adr/f3f0b5bc-743a-4b38-b3c9-7f1376973b7a-validate-ffi-input-using-rust-type-system-and-c-string-conversions-test-suites-include.md new file mode 100644 index 000000000000..ea5690635dd2 --- /dev/null +++ b/docs/adr/f3f0b5bc-743a-4b38-b3c9-7f1376973b7a-validate-ffi-input-using-rust-type-system-and-c-string-conversions-test-suites-include.md @@ -0,0 +1,121 @@ +# Validate FFI Input Using Rust Type System and C String Conversions: Test Suites Include + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary implementations that accept C-compatible string pointers or cryptographic key material from external callers. + +## Context + +- The Rust SDK exposes FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C pointers (c_char) from external callers +- FFI boundaries require explicit validation because Rust's type system cannot enforce safety guarantees across language boundaries where null pointers, invalid UTF-8, or malformed data may be passed +- The codebase uses std::ffi::{c_char, CStr, CString} for bidirectional C string conversion, establishing a pattern of explicit boundary validation +- Test fixtures include five fake RSA private keys (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) used for mocking cryptographic operations, indicating security-sensitive input handling +- The module coordinates with bitwarden_crypto::SymmetricCryptoKey and RSA_POOL, suggesting cryptographic key material flows through these FFI boundaries + +## Problem Statement + +FFI boundaries in Rust expose the system to undefined behavior when external callers pass invalid pointers, malformed UTF-8 sequences, or corrupted cryptographic key material. Without systematic input validation using CStr for null-terminated string verification and type-safe conversions, the SDK risks memory safety violations, panics, or silent corruption of cryptographic operations. + +## Decision + +1. SHOULD: Test suites SHOULD include fake key fixtures (e.g., _FAKE_RSA_KEY_N constants) to validate input handling without requiring real cryptographic material + +## Policy Block + +- SHOULD Test suites SHOULD include fake key fixtures (e.g., _FAKE_RSA_KEY_N constants) to validate input handling without requiring real cryptographic material + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- All modules handling RSA key material via util/RustSdk/rust/src/rsa_keys.rs +- Functions coordinating with bitwarden_crypto::SymmetricCryptoKey or cipher operations +- Memory management functions like free_c_string that deallocate FFI-allocated resources + +Out of scope: +- Pure Rust functions with no FFI exposure +- Internal cryptographic operations within bitwarden_crypto that receive already-validated inputs +- Test-only code paths that do not cross FFI boundaries + +Exceptions: +- EXC-001: Performance-critical inner loops where input has been pre-validated at the FFI entry point + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across two files, indicating an established pattern of explicit FFI boundary validation rather than unsafe pointer dereferencing +- Five fake RSA key constants demonstrate that the codebase tests cryptographic input handling, suggesting security-sensitive validation is a design priority +- The presence of free_c_string in the public API contract indicates memory ownership crosses the FFI boundary, requiring disciplined resource tracking to prevent leaks or double-frees +- Coordination with bitwarden_crypto and RSA_POOL shows that invalid input could corrupt cryptographic state, making input validation a security requirement rather than a convenience + +## Consequences + +Positive: +- Prevents undefined behavior from null pointers, invalid UTF-8, or malformed cryptographic keys at FFI boundaries +- Enables safe interoperation with C/C++ callers while maintaining Rust's memory safety guarantees +- Provides clear error handling paths for invalid input rather than silent corruption or panics +- Establishes testable contracts using fake key fixtures that validate input handling without cryptographic overhead + +Negative: +- Adds validation overhead to every FFI call, potentially impacting performance in high-frequency scenarios +- Requires maintaining parallel test fixtures (fake keys) alongside real cryptographic material +- Increases complexity of FFI function signatures with explicit error handling and resource tracking +- May require refactoring existing FFI code that assumed trusted input or used unsafe pointer operations + +## Alternatives + +- Use unsafe pointer dereferencing without CStr validation, relying on caller contracts (rejected) + Rejected because: Violates Rust safety principles and exposes the system to undefined behavior from malicious or buggy callers. The evidence shows the codebase already uses CStr/CString, indicating this approach was rejected in favor of explicit validation. + When valid: Never valid for production FFI boundaries handling untrusted input +- Validate input only in debug builds using debug_assert, skip validation in release (rejected) + Rejected because: Security-sensitive cryptographic operations require validation in all builds. The presence of fake key fixtures suggests validation is tested, not just asserted. + When valid: Only for internal invariants that cannot be violated by external callers +- Use higher-level FFI bindings (e.g., cbindgen with safer wrappers) to abstract raw pointer handling (deferred) + Rejected because: Not rejected, but not evident in current implementation. May be considered for future refactoring. + When valid: When FFI surface area grows large enough to justify code generation tooling + +## Risks + +- Performance degradation in high-frequency FFI calls due to repeated validation overhead + Mitigation: Profile FFI call paths and consider caching validated inputs or using pre-validated batch operations. Exception EXC-001 allows skipping redundant validation in inner loops. + Owner: Performance engineering team +- Incomplete validation coverage if new FFI functions are added without following CStr/CString patterns + Mitigation: Enforce via code review checklist and CI linting rules that detect c_char usage without corresponding CStr validation + Owner: Security team +- Test fixtures (fake keys) diverge from real key formats, causing validation to pass in tests but fail in production + Mitigation: Generate fake keys using the same tooling as production keys, or derive them from real keys with sensitive data redacted. Periodically validate fake keys against production parsers. + Owner: Cryptography team + +## Implementation Notes + +- Wrap all c_char pointer parameters with unsafe { CStr::from_ptr(ptr) } and handle the Result for UTF-8 validation +- Use CString::new(rust_string)?.into_raw() for outbound strings, and track returned pointers for cleanup via free_c_string +- Maintain fake key constants (_FAKE_RSA_KEY_N) in test modules, ensuring they match production PEM format including BEGIN/END markers +- Document ownership semantics in FFI function comments: specify whether caller or callee owns memory and when free_c_string must be called +- Consider using std::collections::HashSet to track allocated CString pointers and detect double-free attempts in debug builds + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*extern "C"' util/RustSdk/rust/src/ | xargs -I {} sh -c 'grep -A 10 "{}" | grep -q "CStr::from_ptr" || echo "Missing CStr validation: {}"' +- grep -r '_FAKE_RSA_KEY_' util/RustSdk/rust/src/ | wc -l | awk '{if ($1 >= 5) print "PASS: Found", $1, "fake key fixtures"; else print "FAIL: Expected >= 5 fake keys"}' +- cargo test --package rust-sdk --lib -- rsa_keys --nocapture 2>&1 | grep -q 'test result: ok' && echo 'PASS: RSA key validation tests pass' || echo 'FAIL: RSA key tests failed' + +Accept when: +- All FFI functions accepting c_char pointers include CStr::from_ptr validation before dereferencing +- At least 5 fake RSA key fixtures exist in test modules for validating cryptographic input handling +- Cargo test suite for rsa_keys module passes, confirming validation logic handles both valid and invalid inputs + +## Enforcement + +- Verified by: CI pipeline runs grep-based checks for CStr usage patterns in FFI functions +- Verified by: Code review checklist requires security team sign-off on new FFI functions +- Verified by: Cargo test suite includes negative test cases with malformed input (null pointers, invalid UTF-8, corrupted keys) +- Violation handling: CI build fails if FFI functions lack CStr validation patterns +- Violation handling: Security team blocks PR merge until validation is added and tested +- Violation handling: Runtime violations (panics from invalid input) trigger incident review to add missing validation +- Exception process: Submit exception request to security team with performance profiling data justifying the need +- Exception process: Document pre-validation performed at FFI entry point and provide safety argument +- Exception process: Exception approval requires sign-off from both security and cryptography teams \ No newline at end of file diff --git a/docs/adr/f59075ec-7f34-4421-9572-193d3c9ee869-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-use.md b/docs/adr/f59075ec-7f34-4421-9572-193d3c9ee869-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-use.md new file mode 100644 index 000000000000..2ad23a7b5dff --- /dev/null +++ b/docs/adr/f59075ec-7f34-4421-9572-193d3c9ee869-expose-extended-cache-configuration-as-public-api-contract-cache-configuration-use.md @@ -0,0 +1,113 @@ +# Expose Extended Cache Configuration as Public API Contract: Cache Configuration Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase uses Microsoft.Extensions.Caching.StackExchangeRedis and Microsoft.Extensions.Caching.Distributed for distributed caching infrastructure +- ExtendedCacheServiceCollectionExtensions provides a public API surface for configuring cache services with Redis connection multiplexer support +- The implementation includes error logging via ILogger when Redis connection failures occur, indicating production-grade reliability requirements +- The extension method AddExtendedCache is exposed as a public contract in the Bit.Core.Utilities namespace, suggesting it is intended for consumption by multiple service registration points + +## Problem Statement + +Distributed cache configuration requires consistent setup across multiple services and environments, but without a standardized public API contract, each service may implement Redis connection handling, error logging, and cache registration differently, leading to inconsistent reliability patterns and maintenance burden. + +## Decision + +1. MUST: Cache configuration MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client implementation + +## Policy Block + +- MUST Cache configuration MUST use Microsoft.Extensions.Caching.StackExchangeRedis as the Redis client implementation + +In scope: +- All service registration code using distributed Redis caching +- Cache initialization in Bit.Core.Utilities namespace +- IDistributedCache implementations backed by Redis +- Service collection extension methods for cache configuration + +Out of scope: +- In-memory cache implementations (IMemoryCache) +- Non-Redis distributed cache providers +- Application-level cache usage patterns (cache consumers) +- Cache key naming conventions and expiration policies + +## Rationale + +- The evidence shows a public API contract (ExtendedCacheServiceCollectionExtensions.AddExtendedCache) that standardizes Redis cache registration across the codebase +- Error logging with structured context (cache name) indicates production reliability requirements that should be consistently applied +- Use of StackExchangeRedis with ConnectionMultiplexer.Connect demonstrates a specific technical choice that should be enforced for consistency +- The public visibility and extension method pattern suggests this is intended as a reusable contract for multiple consuming services + +## Consequences + +Positive: +- Consistent Redis connection handling and error logging across all services using distributed caching +- Reduced duplication of cache configuration logic through centralized public API +- Improved debuggability through standardized error logging with cache name context +- Clear contract for service registration that can be tested and validated independently + +Negative: +- Tight coupling to StackExchangeRedis library makes switching Redis clients more difficult +- Public API contract creates breaking change risk if cache configuration requirements evolve +- Additional abstraction layer may obscure underlying Redis configuration for developers unfamiliar with the extension +- Centralized error handling may not accommodate service-specific retry or fallback strategies + +## Alternatives + +- Use Microsoft.Extensions.Caching.StackExchangeRedis directly without custom extension methods (rejected) + Rejected because: Direct usage would duplicate Redis connection error handling and logging logic across multiple service registration points, reducing consistency and increasing maintenance burden + When valid: For simple applications with a single cache registration point where the overhead of an extension method is not justified +- Create an abstract ICacheProvider interface to decouple from StackExchangeRedis implementation (rejected) + Rejected because: The evidence shows direct use of StackExchangeRedis types (ConnectionMultiplexer) indicating the codebase has accepted coupling to this specific implementation + When valid: When multi-provider cache support is required or when Redis client library migration is anticipated +- Use configuration-based cache registration via appsettings.json without code-based extensions (rejected) + Rejected because: Configuration-only approach cannot provide structured error logging with ILogger injection or programmatic connection multiplexer setup as evidenced in the implementation + When valid: For simple cache scenarios without custom connection handling or error logging requirements + +## Risks + +- Breaking changes to ExtendedCacheServiceCollectionExtensions public API would impact all consuming services + Mitigation: Version the API contract and maintain backward compatibility through overloads or optional parameters; use semantic versioning for Bit.Core.Utilities package + Owner: Core utilities team +- StackExchangeRedis library vulnerabilities or deprecation would require changes across all cache consumers + Mitigation: Monitor StackExchangeRedis security advisories and version updates; maintain abstraction boundary in ExtendedCacheServiceCollectionExtensions to isolate implementation details + Owner: Security and infrastructure team +- Centralized error logging may not capture service-specific context needed for debugging cache issues + Mitigation: Ensure ILogger includes sufficient structured context (cache name, connection string sanitized); allow services to add additional logging via composition + Owner: Engineering team + +## Implementation Notes + +- Import Bit.Core.Utilities and call AddExtendedCache on IServiceCollection during service registration +- Ensure ILogger is registered in the service collection before calling AddExtendedCache to enable connection error logging +- Configure Redis connection strings via Bit.Core.Settings to maintain consistency with the extension's expected configuration source +- Review existing direct StackExchangeRedis registrations and migrate to AddExtendedCache to standardize error handling + +## Continuation Context + + +Verify commands: +- grep -r 'AddExtendedCache' --include='*.cs' / +- grep -r 'AddStackExchangeRedisCache' --include='*.cs' / | grep -v 'ExtendedCacheServiceCollectionExtensions' +- grep -r 'LogError.*Failed to connect to Redis' --include='*.cs' / + +Accept when: +- All service registration code uses AddExtendedCache instead of direct AddStackExchangeRedisCache calls +- Redis connection error logging includes cache name context via ILogger.LogError +- No direct ConnectionMultiplexer.Connect calls exist outside ExtendedCacheServiceCollectionExtensions + +## Enforcement + +- Verified by: Code review checklist requiring AddExtendedCache usage for new cache registrations +- Verified by: Static analysis rules detecting direct StackExchangeRedis registration outside approved extension methods +- Verified by: Integration tests validating error logging behavior during Redis connection failures +- Violation handling: CI pipeline fails if direct AddStackExchangeRedisCache usage is detected outside ExtendedCacheServiceCollectionExtensions +- Violation handling: Pull requests with non-compliant cache registration are blocked until migrated to AddExtendedCache +- Violation handling: Quarterly audit of cache registration patterns with remediation tracking for violations +- Exception process: Submit exception request to architecture review board with justification for alternative cache provider or configuration +- Exception process: Document approved exceptions in ADR amendments with specific scope and expiration date +- Exception process: Exceptions require sign-off from core utilities team and security team for production deployments \ No newline at end of file diff --git a/docs/adr/f5ec24ef-0f13-4808-a252-ebb15c6726e0-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-integration-tests-call.md b/docs/adr/f5ec24ef-0f13-4808-a252-ebb15c6726e0-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-integration-tests-call.md new file mode 100644 index 000000000000..a782fc48e1fd --- /dev/null +++ b/docs/adr/f5ec24ef-0f13-4808-a252-ebb15c6726e0-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-integration-tests-call.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Integration Tests Call + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. MUST: Integration tests MUST call DatabaseContext.SaveChanges() explicitly to persist test data before executing HTTP requests against SCIM endpoints + +## Policy Block + +- MUST Integration tests MUST call DatabaseContext.SaveChanges() explicitly to persist test data before executing HTTP requests against SCIM endpoints + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/f608c3ab-b657-400c-b7e6-9bea9ad78794-standardize-authorization-policy-configuration-with-named-scopes-test-environments-use.md b/docs/adr/f608c3ab-b657-400c-b7e6-9bea9ad78794-standardize-authorization-policy-configuration-with-named-scopes-test-environments-use.md new file mode 100644 index 000000000000..fb15327c82b4 --- /dev/null +++ b/docs/adr/f608c3ab-b657-400c-b7e6-9bea9ad78794-standardize-authorization-policy-configuration-with-named-scopes-test-environments-use.md @@ -0,0 +1,117 @@ +# Standardize Authorization Policy Configuration with Named Scopes: Test Environments Use + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring authorization enforcement at the API boundary level +- Authorization policies are configured using AddAuthorization with named policy definitions ('Scim') that specify authentication and claim requirements +- Two distinct authorization configurations exist: a test environment using policy.RequireAssertion(a => true) for permissive testing, and a production environment using policy.RequireAuthenticatedUser() with policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- The pattern appears in Startup.cs for production configuration and ScimApplicationFactory.cs for integration test setup, indicating a consistent approach to authorization policy definition across environments +- Authentication is configured using AddAuthentication with scheme-based handlers (ApiKeyAuthenticationOptions.DefaultScheme in production, 'Test' scheme in testing) before authorization policies are applied + +## Problem Statement + +Authorization enforcement points in API applications require consistent, testable, and maintainable configuration patterns that can adapt across production and test environments while ensuring security requirements are explicitly documented and verifiable through policy definitions. + +## Decision + +1. SHOULD: Test environments SHOULD use permissive authorization policies (RequireAssertion) to enable integration testing without external authentication dependencies + +## Policy Block + +- SHOULD Test environments SHOULD use permissive authorization policies (RequireAssertion) to enable integration testing without external authentication dependencies + +In scope: +- ASP.NET Core applications using AddAuthorization for policy-based authorization +- SCIM API endpoints requiring scope-based access control +- Services using ApiKeyAuthenticationHandler or custom authentication schemes +- Integration test factories requiring authorization policy configuration + +Out of scope: +- Attribute-based authorization using [Authorize] without named policies +- Role-based authorization not using claim-based policies +- Authorization logic implemented in middleware or controllers directly +- External authorization services or policy decision points + +Exceptions: +- EXC-001: Integration test environments require permissive authorization to test business logic without authentication infrastructure + +## Rationale + +- The evidence shows consistent use of AddAuthorization with named policies across both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts, indicating an established pattern for authorization configuration +- Explicit claim-based authorization using JwtClaimTypes.Scope provides fine-grained access control aligned with OAuth 2.0 scope semantics, enabling API-level authorization boundaries +- Separation of authentication scheme configuration (AddAuthentication) from authorization policy configuration (AddAuthorization) follows ASP.NET Core architectural patterns and enables independent testing and configuration of each concern +- The pattern supports environment-specific authorization behavior while maintaining consistent policy naming and structure, reducing cognitive load and configuration errors + +## Consequences + +Positive: +- Centralized authorization policy configuration improves auditability and compliance verification for security requirements +- Named policies enable reusable authorization logic that can be referenced across multiple controllers and endpoints +- Explicit claim requirements document security boundaries in code, making authorization requirements discoverable through static analysis +- Test-specific authorization configurations enable comprehensive integration testing without compromising production security posture + +Negative: +- Policy-based authorization adds configuration complexity compared to simple attribute-based authorization +- Divergence between test and production authorization policies may mask security issues that only surface in production +- Named policy strings create runtime coupling that cannot be verified at compile time, increasing risk of configuration errors +- Claim-based authorization requires coordination with authentication token issuance, creating cross-cutting dependencies + +## Alternatives + +- Use attribute-based authorization with [Authorize(Policy = "Scim")] directly on controllers without centralized policy configuration (rejected) + Rejected because: Decentralized policy definitions would duplicate authorization logic across controllers and reduce visibility into security requirements + When valid: Simple applications with single authorization requirement and no need for policy reuse +- Implement custom authorization middleware with inline authorization logic instead of policy-based configuration (rejected) + Rejected because: Custom middleware would bypass ASP.NET Core authorization framework, losing built-in policy evaluation, logging, and integration with authentication + When valid: Applications with highly specialized authorization requirements not supported by policy framework +- Use role-based authorization with [Authorize(Roles = "ScimAdmin")] instead of claim-based scope authorization (rejected) + Rejected because: Role-based authorization does not align with OAuth 2.0 scope semantics required for API authorization and provides coarser-grained access control + When valid: Internal applications with user-centric role models rather than API scope-based access control + +## Risks + +- Test authorization policies using RequireAssertion(a => true) may be accidentally deployed to production, bypassing all authorization checks + Mitigation: Implement environment-specific configuration validation in CI/CD pipeline to detect permissive authorization policies in production builds + Owner: Security engineering team +- Policy name strings ('Scim') are not compile-time verified, leading to runtime authorization failures if policy names are mismatched between configuration and controller attributes + Mitigation: Define policy names as constants in shared configuration class and reference constants in both policy configuration and controller attributes + Owner: Engineering team +- Claim-based authorization depends on correct token issuance by authentication provider; misconfigured claims in tokens will cause authorization failures + Mitigation: Implement integration tests validating end-to-end authentication and authorization flow with realistic token payloads + Owner: Platform engineering team + +## Implementation Notes + +- Configure authentication schemes using AddAuthentication before calling AddAuthorization to ensure authentication context is available for policy evaluation +- Use IOptions or similar configuration objects to externalize policy requirements (scope names, claim types) rather than hardcoding in Startup +- Document authorization policy requirements in API documentation (OpenAPI/Swagger) to communicate security requirements to API consumers +- Implement logging in authorization policy handlers to capture authorization decisions for security auditing and troubleshooting + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -v 'RequireAssertion' # Verify production code does not use permissive test policies +- grep -r 'RequireAuthenticatedUser\|RequireClaim' --include='Startup.cs' # Confirm production authorization requires authentication and claims +- grep -r 'policy.AddPolicy' --include='*.cs' -A 5 | grep -E '(RequireAuthenticatedUser|RequireClaim)' # Validate policy definitions include security requirements + +Accept when: +- All production Startup.cs files contain AddAuthorization with policies using RequireAuthenticatedUser() and RequireClaim() +- Test factory classes use RequireAssertion only in test-specific configuration files (e.g., *ApplicationFactory.cs, *TestStartup.cs) +- No production configuration files contain authorization policies with RequireAssertion(a => true) or other permissive assertions + +## Enforcement + +- Verified by: Static code analysis scanning for authorization policy configurations in CI/CD pipeline +- Verified by: Security-focused code review checklist requiring verification of authorization policy definitions +- Verified by: Automated integration tests validating authorization behavior with valid and invalid tokens +- Violation handling: CI/CD pipeline fails builds containing permissive authorization policies (RequireAssertion) in production code paths +- Violation handling: Security team review required for any authorization policy changes before merge to main branch +- Violation handling: Runtime monitoring alerts on authorization failures to detect misconfigured policies in production +- Exception process: Exception requests must document specific business justification for deviation from standard authorization patterns +- Exception process: Security architect approval required for any exceptions to claim-based authorization requirements +- Exception process: Approved exceptions must include compensating controls and time-bound remediation plan \ No newline at end of file diff --git a/docs/adr/f6bde425-ff4b-4ba8-9610-7c913f3a12ec-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-scim-endpoint-authorization.md b/docs/adr/f6bde425-ff4b-4ba8-9610-7c913f3a12ec-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-scim-endpoint-authorization.md new file mode 100644 index 000000000000..a4a2e168a83a --- /dev/null +++ b/docs/adr/f6bde425-ff4b-4ba8-9610-7c913f3a12ec-enforce-authorization-policies-via-addauthorization-configuration-in-asp-net-core-scim-endpoint-authorization.md @@ -0,0 +1,126 @@ +# Enforce Authorization Policies via AddAuthorization Configuration in ASP.NET Core: Scim Endpoint Authorization + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all ASP.NET Core services implementing authorization policies. + +## Context + +- The codebase implements SCIM (System for Cross-domain Identity Management) endpoints requiring fine-grained authorization controls beyond basic authentication +- ASP.NET Core provides a policy-based authorization framework through services.AddAuthorization() that separates authorization logic from controller code +- Two distinct authorization policies are observed: a test policy with RequireAssertion(a => true) for integration testing, and a production policy requiring authenticated users with 'api.scim' scope claims +- The authorization enforcement points are configured during service registration in Startup.cs and ScimApplicationFactory.cs, establishing centralized policy definitions before the request pipeline executes + +## Problem Statement + +Services exposing SCIM APIs require consistent authorization enforcement that validates both user authentication and specific scope claims (api.scim) without embedding authorization logic directly in controller methods, while maintaining separate authorization behavior for integration testing scenarios. + +## Decision + +1. MUST: SCIM endpoint authorization policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, "api.scim") + +## Policy Block + +- MUST SCIM endpoint authorization policies MUST require the 'api.scim' scope claim using policy.RequireClaim(JwtClaimTypes.Scope, "api.scim") + +In scope: +- All ASP.NET Core services exposing SCIM v2 endpoints +- Services using ApiKeyAuthenticationHandler or equivalent authentication schemes +- Integration test factories (ScimApplicationFactory) requiring authorization bypass +- Controllers decorated with [Authorize(Policy = "Scim")] or equivalent policy attributes + +Out of scope: +- Non-SCIM endpoints that may use different authorization policies +- Services using attribute-based authorization without policy configuration +- External authentication providers (policy configuration is internal to the service) +- Authorization logic embedded directly in controller action methods + +Exceptions: +- EXC-001: Integration tests require authorization bypass to test endpoint behavior without full authentication infrastructure + +## Rationale + +- Centralized authorization policy configuration in services.AddAuthorization() separates authorization concerns from business logic, improving maintainability and testability +- The pattern appears in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with 78.70% confidence across 2 files, indicating consistent adoption for SCIM endpoint protection +- Policy-based authorization enables declarative security requirements that can be verified at compile-time through policy name references and modified without changing controller code +- The requirement for 'api.scim' scope claims aligns with OAuth 2.0 scope-based access control patterns for API authorization + +## Consequences + +Positive: +- Authorization logic is centralized and reusable across multiple controllers through named policy references +- Test environments can override authorization behavior without modifying production code paths +- Policy requirements are explicit and auditable through service configuration inspection +- Changes to authorization requirements require modification in a single location rather than across multiple controllers + +Negative: +- Authorization policy configuration is separated from the controllers that use it, requiring developers to navigate between files to understand full authorization behavior +- Test-specific authorization policies introduce configuration divergence between test and production environments that must be carefully managed +- Policy-based authorization adds framework-specific coupling to ASP.NET Core authorization abstractions +- Complex authorization requirements may require custom policy handlers, increasing implementation complexity + +## Alternatives + +- Implement authorization logic directly in controller action methods using imperative checks (rejected) + Rejected because: Imperative authorization scatters security logic across multiple controllers, making it difficult to audit and maintain consistent authorization rules + When valid: Valid for simple applications with minimal authorization requirements or one-off authorization checks that don't fit policy patterns +- Use attribute-based authorization with role requirements ([Authorize(Roles = "Admin")]) instead of policy-based authorization (rejected) + Rejected because: Role-based authorization cannot express the compound requirement of authenticated user + specific scope claim ('api.scim') without custom authorization attributes + When valid: Valid for simple role-based access control scenarios without scope or claim requirements +- Implement custom authorization middleware that validates claims before reaching controllers (rejected) + Rejected because: Custom middleware duplicates ASP.NET Core's built-in policy framework and loses integration with [Authorize] attributes and policy-based endpoint routing + When valid: Valid when authorization requirements cannot be expressed through policy framework or when cross-cutting authorization logic applies to all endpoints + +## Risks + +- Test authorization policies using RequireAssertion(a => true) could accidentally be deployed to production, bypassing all authorization checks + Mitigation: Isolate test-specific authorization configuration to test application factories; add CI checks to verify production Startup.cs does not contain RequireAssertion(a => true); use environment-specific configuration validation + Owner: Engineering team and DevOps +- Policy name mismatches between services.AddAuthorization() configuration and [Authorize(Policy = "...")] attributes will fail silently at runtime rather than compile-time + Mitigation: Implement integration tests that verify all referenced policy names exist; use constants for policy names instead of string literals; add startup validation that checks policy references + Owner: Engineering team +- Changes to claim requirements (e.g., modifying 'api.scim' scope) require coordinated updates across authentication providers and authorization policies + Mitigation: Document claim contracts in API specifications; use constants for claim types and values; implement contract tests between authentication and authorization components + Owner: Engineering team and API governance + +## Implementation Notes + +- Register authorization policies in ConfigureServices/Startup.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { ... }); }) +- Apply policies to controllers or actions using [Authorize(Policy = "Scim")] attribute decoration +- Ensure app.UseAuthentication() is called before app.UseAuthorization() in the request pipeline configuration to establish authentication context before authorization evaluation +- For integration tests, create separate application factories that override authorization configuration with test-specific policies +- Use JwtClaimTypes constants from IdentityModel library for standardized claim type references (e.g., JwtClaimTypes.Scope) + +## Continuation Context + + +Verify commands: +- grep -r 'services.AddAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r 'policy.RequireClaim.*api.scim' --include='*.cs' bitwarden_license/src/Scim/Startup.cs +- grep -r 'app.UseAuthentication.*app.UseAuthorization' --include='*.cs' bitwarden_license/src/Scim/ +- grep -r '\[Authorize.*Policy.*Scim' --include='*.cs' bitwarden_license/src/Scim/ + +Accept when: +- services.AddAuthorization() configuration exists in Startup.cs with a named policy requiring authenticated users and 'api.scim' scope claim +- app.UseAuthorization() is called after app.UseAuthentication() in the request pipeline configuration +- Controllers or actions reference the authorization policy by name using [Authorize(Policy = "...")] attributes +- Test application factories define separate authorization policies isolated from production configuration + +## Enforcement + +- Verified by: Code review verification that authorization policies are registered in Startup.cs with required claim checks +- Verified by: Integration tests that verify unauthorized requests return 401/403 status codes +- Verified by: Static analysis scanning for [Authorize] attributes without corresponding policy registrations +- Verified by: CI pipeline checks that production Startup.cs does not contain test-specific authorization bypass patterns +- Violation handling: Pull requests adding SCIM endpoints without corresponding authorization policy configuration are rejected during code review +- Violation handling: Integration tests failing authorization checks block deployment pipelines +- Violation handling: Security audits flag endpoints lacking policy-based authorization for remediation +- Violation handling: Runtime authorization failures are logged and monitored for policy misconfiguration detection +- Exception process: Exceptions to policy-based authorization require security team review and documented justification +- Exception process: Test-specific authorization bypasses must be isolated to test application factories and never appear in production Startup.cs +- Exception process: Alternative authorization mechanisms (custom middleware, imperative checks) require architectural review and ADR documentation +- Exception process: Temporary authorization bypasses for development must be tracked as technical debt with remediation timelines \ No newline at end of file diff --git a/docs/adr/f6f6d796-e5f5-455e-9ee0-463991270cce-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-operations-cipher.md b/docs/adr/f6f6d796-e5f5-455e-9ee0-463991270cce-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-operations-cipher.md new file mode 100644 index 000000000000..fd927144a8de --- /dev/null +++ b/docs/adr/f6f6d796-e5f5-455e-9ee0-463991270cce-adopt-ffi-based-cryptographic-key-management-with-mocking-support-in-rust-sdk-cryptographic-operations-cipher.md @@ -0,0 +1,117 @@ +# Adopt FFI-Based Cryptographic Key Management with Mocking Support in Rust SDK: Cryptographic Operations Cipher + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation and management functions through a C FFI boundary, requiring explicit handling of C-compatible types (c_char, CStr, CString) for cross-language interoperability +- The codebase models cryptographic primitives (cipher, rsa_keys) and key generation workflows (generate_user_keys, generate_organization_keys, generate_user_organization_key) as first-class data structures with public contracts +- Testing infrastructure requires mocking capabilities for cryptographic operations, as evidenced by the testing.mocking facet detection for cipher and rsa_keys components +- The implementation uses bitwarden_crypto::SymmetricCryptoKey and maintains an RSA_POOL resource, indicating centralized key material management with potential pooling or caching semantics +- Input validation patterns are detected across cipher and key management functions, suggesting defensive programming at the FFI boundary where type safety is weakened + +## Problem Statement + +Cryptographic key management in FFI contexts requires explicit data modeling decisions that balance type safety, testability, and cross-language contract stability. Without standardized patterns for modeling key material, generation workflows, and mock boundaries, teams risk inconsistent validation, untestable cryptographic paths, and brittle FFI contracts that break when internal representations change. + +## Decision + +1. SHOULD: Cryptographic operations (cipher, rsa_keys) SHOULD provide mock implementations or test doubles to enable unit testing without real key material + +## Policy Block + +- SHOULD Cryptographic operations (cipher, rsa_keys) SHOULD provide mock implementations or test doubles to enable unit testing without real key material + +In scope: +- All Rust SDK FFI functions in util/RustSdk/rust/src/lib.rs that handle cryptographic key material +- Public key generation APIs (generate_user_keys, generate_organization_keys, generate_user_organization_key) +- Cipher and RSA key data structures exposed across FFI boundaries +- Test infrastructure requiring mock implementations of cryptographic primitives + +Out of scope: +- Internal cryptographic algorithm implementations within bitwarden_crypto crate +- Non-FFI Rust-only key management APIs that do not cross language boundaries +- Key storage and persistence mechanisms (file system, secure enclaves, key stores) +- Network protocols for key exchange or distribution + +Exceptions: +- EXC-001: Performance-critical internal paths that do not cross FFI boundaries + +## Rationale + +- The evidence shows explicit FFI type handling (c_char, CStr, CString) in 39 detected instances within util/RustSdk/rust/src/lib.rs, indicating a deliberate architectural boundary between Rust and C-compatible consumers +- Detection of testing.mocking facet for cipher and rsa_keys with 91% confidence suggests the codebase has evolved to support testability requirements for cryptographic operations +- Public contracts (pub) for key generation functions combined with memory management (free_c_string) demonstrate awareness of FFI ownership semantics and cross-language lifecycle management +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL indicates a layered architecture where high-level key management abstractions coordinate lower-level cryptographic primitives + +## Consequences + +Positive: +- Explicit FFI-safe data modeling prevents memory safety issues and undefined behavior at language boundaries +- Mock support for cryptographic operations enables comprehensive unit testing without requiring real key material or hardware security modules +- Centralized key resource management (RSA_POOL) reduces redundant key generation overhead and improves performance +- Public contracts with clear ownership semantics (free_c_string) make FFI integration predictable for C/C++ consumers + +Negative: +- FFI type conversions (CStr/CString) add runtime overhead and increase code complexity at boundary layers +- Mocking infrastructure requires maintaining parallel test implementations that may diverge from production cryptographic behavior +- Centralized resource pools (RSA_POOL) introduce potential contention points and complicate lifecycle management in multi-threaded contexts +- Input validation at every FFI entry point increases code volume and maintenance burden + +## Alternatives + +- Use opaque pointer handles at FFI boundary instead of explicit C string conversions (rejected) + Rejected because: Opaque pointers reduce debuggability and require additional handle management infrastructure, while the current approach provides transparent string-based contracts that are easier to inspect and validate + When valid: When FFI consumers require high-frequency calls where string conversion overhead becomes a measurable bottleneck +- Embed mock behavior directly in production types using conditional compilation (rejected) + Rejected because: Mixing production and test code paths within the same types increases binary size, complicates security audits, and risks accidental test code execution in production builds + When valid: In prototype or development-only builds where binary size and security audit scope are not concerns +- Generate FFI bindings automatically from Rust types using cbindgen or similar tools (deferred) + Rejected because: Not rejected; may be adopted in future to reduce manual FFI maintenance burden, but requires evaluation of generated contract stability and compatibility with existing C consumers + When valid: When FFI surface area grows large enough that manual maintenance becomes error-prone, and tooling maturity supports stable contract generation + +## Risks + +- FFI string conversions may fail or panic on invalid UTF-8 input from C callers, causing undefined behavior or crashes + Mitigation: Implement defensive validation using CStr::from_ptr safety checks and return error codes to C callers instead of panicking + Owner: Rust SDK team +- Mock implementations may not accurately reflect production cryptographic behavior, leading to false test confidence + Mitigation: Maintain integration tests using real cryptographic operations alongside unit tests with mocks; document mock limitations explicitly + Owner: Security and QA teams +- Centralized RSA_POOL may become a concurrency bottleneck or single point of failure in high-throughput scenarios + Mitigation: Monitor pool contention metrics; consider sharded pool design or per-thread key caches if contention is observed + Owner: Performance engineering team + +## Implementation Notes + +- Use #[repr(C)] attribute on all data structures crossing FFI boundaries to ensure stable memory layout +- Wrap all CStr::from_ptr calls in unsafe blocks with explicit null pointer checks and UTF-8 validation +- Define mock traits (e.g., CipherOps, RsaKeyOps) that both production and test implementations can satisfy, using dependency injection or feature flags to select implementations +- Document memory ownership semantics in FFI function comments: specify which side (Rust or C) owns allocated memory and when free_c_string must be called + +## Continuation Context + + +Verify commands: +- grep -r 'pub.*fn.*generate.*keys' util/RustSdk/rust/src/lib.rs | grep -c 'pub' # Should find public key generation functions +- grep -r 'use std::ffi::{c_char, CStr, CString}' util/RustSdk/rust/src/lib.rs # Should confirm FFI type usage +- cargo test --package bitwarden-crypto --lib -- --test-threads=1 # Should pass with mock implementations + +Accept when: +- All public FFI functions handling key material use std::ffi types (c_char, CStr, CString) with explicit validation +- Mock implementations exist for cipher and rsa_keys components enabling unit tests to run without real cryptographic operations +- Memory management functions (free_c_string) are provided and documented for all FFI-allocated strings + +## Enforcement + +- Verified by: Automated code review checks for FFI functions missing input validation or proper error handling +- Verified by: CI pipeline runs both unit tests (with mocks) and integration tests (with real crypto) to verify dual implementation correctness +- Verified by: Security team audits FFI boundary code during quarterly security reviews +- Violation handling: CI build fails if FFI functions lack required validation or memory management functions +- Violation handling: Pull requests adding new FFI entry points require security team approval +- Violation handling: Runtime panics in FFI code trigger incident review and post-mortem analysis +- Exception process: Request exception through security team with documented performance or compatibility rationale +- Exception process: Exception approval requires compensating controls (e.g., additional integration testing, runtime monitoring) +- Exception process: Exceptions are time-limited and reviewed quarterly for continued necessity \ No newline at end of file diff --git a/docs/adr/f766c552-4097-49a8-ab9c-efc885073a79-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md b/docs/adr/f766c552-4097-49a8-ab9c-efc885073a79-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md new file mode 100644 index 000000000000..81991110c625 --- /dev/null +++ b/docs/adr/f766c552-4097-49a8-ab9c-efc885073a79-validate-ffi-string-inputs-using-cstr-cstring-conversion-in-rust-sdk-ffi-functions-returning.md @@ -0,0 +1,122 @@ +# Validate FFI String Inputs Using CStr/CString Conversion in Rust SDK: Ffi Functions Returning + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes FFI (Foreign Function Interface) boundaries using C-compatible types (c_char pointers) to enable interoperability with non-Rust code +- Raw C string pointers from external callers require validation to prevent null pointer dereferences, invalid UTF-8 sequences, and buffer overruns +- The codebase handles cryptographic operations (SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) where input validation failures could lead to security vulnerabilities +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) accept external input that must be sanitized before use +- The std::ffi module provides CStr and CString types specifically designed for safe FFI string handling with built-in validation + +## Problem Statement + +External callers passing malformed or malicious string data through FFI boundaries can cause undefined behavior, memory corruption, or security vulnerabilities in cryptographic operations if input validation is not consistently applied at the interface boundary. + +## Decision + +1. MUST: FFI functions returning string data to external callers MUST use CString::into_raw or equivalent to ensure null-terminated C-compatible strings + +## Policy Block + +- MUST FFI functions returning string data to external callers MUST use CString::into_raw or equivalent to ensure null-terminated C-compatible strings + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs accepting c_char pointers +- Functions handling cryptographic material (cipher, rsa_keys, SymmetricCryptoKey) +- Public API functions: generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string +- Any function marked with #[no_mangle] or extern "C" that accepts string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries +- String handling within pure Rust modules using native String/&str types +- Test code and mocking frameworks unless testing FFI behavior +- Functions that accept only numeric or pointer-to-struct FFI parameters + +Exceptions: +- EXC-001: FFI function is internal-only and called exclusively by trusted Rust code with pre-validated inputs + +## Rationale + +- Evidence shows consistent use of std::ffi::{c_char, CStr, CString} across FFI boundaries in util/RustSdk/rust/src/lib.rs, indicating established pattern for safe string handling +- The presence of cryptographic operations (bitwarden_crypto::SymmetricCryptoKey, RSA_POOL, cipher, rsa_keys) elevates the security risk of input validation failures +- Public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) expose attack surface requiring defense-in-depth validation +- CStr/CString types provide memory-safe validation that prevents common FFI vulnerabilities (null pointer dereferences, buffer overruns, invalid UTF-8) without performance overhead + +## Consequences + +Positive: +- Prevents undefined behavior and memory corruption from malformed C string inputs at FFI boundaries +- Reduces attack surface for cryptographic operations by validating inputs before sensitive processing +- Provides clear error handling paths for invalid inputs rather than crashes or panics +- Leverages Rust's type system (CStr/CString) to enforce validation at compile time where possible + +Negative: +- Adds validation overhead to every FFI string operation, though typically negligible compared to cryptographic work +- Requires explicit error handling code paths for validation failures, increasing code complexity +- May require coordination with external callers to handle validation errors appropriately +- Memory management for CString returns requires careful coordination with free_c_string to prevent leaks + +## Alternatives + +- Use raw pointer arithmetic and manual null-terminator checking without CStr/CString wrappers (rejected) + Rejected because: Manual validation is error-prone and bypasses Rust's memory safety guarantees, increasing vulnerability risk + When valid: Never recommended for new code; only acceptable when maintaining legacy C interop code +- Accept only length-prefixed strings (pointer + length) instead of null-terminated C strings (rejected) + Rejected because: Breaks compatibility with standard C FFI conventions and requires custom calling conventions + When valid: Valid for internal Rust-to-Rust FFI where both sides control the interface contract +- Use higher-level FFI binding generators (cbindgen, cxx) to automate safe string handling (deferred) + Rejected because: Not rejected; could complement this pattern but requires tooling investment and build process changes + When valid: Valid for new FFI interfaces or major refactoring efforts with tooling support + +## Risks + +- Inconsistent application of validation across FFI functions creates gaps in security boundary + Mitigation: Implement automated verification (grep/clippy lints) to detect FFI functions missing CStr validation + Owner: Security team and Rust SDK maintainers +- Memory leaks if external callers fail to call free_c_string on returned CString pointers + Mitigation: Document memory ownership clearly in API documentation; consider RAII wrappers for managed language bindings + Owner: SDK documentation team and binding maintainers +- Validation errors may be silently ignored by external callers expecting infallible APIs + Mitigation: Use explicit error return codes; log validation failures for monitoring; provide clear error documentation + Owner: Engineering team and API design reviewers + +## Implementation Notes + +- Use CStr::from_ptr() wrapped in unsafe block for incoming c_char pointers; check for null before dereferencing +- Convert CStr to Rust String using .to_str() or .to_string_lossy() depending on UTF-8 requirements +- For return values, use CString::new() to create owned string, then CString::into_raw() to transfer ownership to caller +- Implement free_c_string as: unsafe { CString::from_raw(ptr) } to reclaim and drop the memory +- Consider using Result return types with error codes mapped to C-compatible integers for validation failures + +## Continuation Context + + +Verify commands: +- grep -n 'extern "C"' util/RustSdk/rust/src/lib.rs | grep -E 'c_char|\*const|\*mut' | wc -l +- grep -n 'CStr::from_ptr\|CString::' util/RustSdk/rust/src/lib.rs | wc -l +- cargo clippy -- -W clippy::not_unsafe_ptr_arg_deref 2>&1 | grep -c 'warning\|error' + +Accept when: +- All extern C functions accepting c_char pointers use CStr::from_ptr for validation +- All extern C functions returning strings use CString::into_raw for safe memory transfer +- Clippy lints for unsafe pointer dereference produce zero warnings in FFI code +- Code review confirms validation occurs before cryptographic operations + +## Enforcement + +- Verified by: Automated grep/pattern matching in CI pipeline to detect FFI functions with c_char parameters +- Verified by: Cargo clippy with unsafe pointer lints enabled in CI builds +- Verified by: Mandatory security-focused code review for all changes to FFI boundary functions +- Verified by: Static analysis tools scanning for CStr/CString usage patterns at FFI boundaries +- Violation handling: CI build fails if FFI functions lack CStr/CString validation patterns +- Violation handling: Security team review required for any FFI function bypassing standard validation +- Violation handling: Post-merge audits flag violations for immediate remediation +- Violation handling: Violations in cryptographic code paths trigger security incident review +- Exception process: Submit exception request to security team with justification and risk assessment +- Exception process: Document trust boundary and validation responsibility in function documentation +- Exception process: Require explicit approval from two security team members for cryptographic FFI exceptions +- Exception process: Record exception in security decision log with expiration date for re-review \ No newline at end of file diff --git a/docs/adr/f8dc926d-f900-4ef3-aae4-f2117e32e004-adopt-test-authentication-scheme-for-integration-testing-test-authentication-configuration.md b/docs/adr/f8dc926d-f900-4ef3-aae4-f2117e32e004-adopt-test-authentication-scheme-for-integration-testing-test-authentication-configuration.md new file mode 100644 index 000000000000..767cfae2ff68 --- /dev/null +++ b/docs/adr/f8dc926d-f900-4ef3-aae4-f2117e32e004-adopt-test-authentication-scheme-for-integration-testing-test-authentication-configuration.md @@ -0,0 +1,102 @@ +# Adopt Test Authentication Scheme for Integration Testing: Test Authentication Configuration + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests require authentication middleware to validate request authorization without external identity providers +- The ASP.NET Core authentication pipeline uses AddAuthentication() to register authentication schemes that can be configured for test environments +- Test authentication handlers extend AuthenticationHandler to provide deterministic claims without network dependencies +- The Scim.IntegrationTest and Sso projects demonstrate authentication configuration patterns where test schemes bypass production authentication flows + +## Problem Statement + +Integration tests must authenticate requests through the ASP.NET Core authentication pipeline without depending on external identity providers, production credentials, or network-accessible authentication services, while maintaining the same authorization policy enforcement as production code. + +## Decision + +1. MAY: Test authentication configuration MAY be combined with AddAuthorization() to configure test-specific authorization policies + +## Policy Block + +- MAY Test authentication configuration MAY be combined with AddAuthorization() to configure test-specific authorization policies + +## Rationale + +- The evidence shows TestAuthHandler in ScimApplicationFactory.cs implementing AuthenticationHandler with HandleAuthenticateAsync() returning deterministic claims including 'orgadmin' organization identifiers +- Both Scim.IntegrationTest and Sso projects call AddAuthentication() during service configuration, establishing authentication middleware in the test pipeline +- The pattern enables integration tests to execute authorization policies (e.g., 'Scim' policy with RequireAssertion) without external authentication dependencies +- Test authentication schemes provide controlled claim sets that satisfy authorization requirements while maintaining test isolation and repeatability + +## Consequences + +Positive: +- Integration tests execute with deterministic authentication state, eliminating flakiness from external identity provider dependencies +- Authorization policies are validated in integration tests using the same middleware pipeline as production +- Test execution speed improves by removing network calls to authentication services +- Test claims can be tailored to specific test scenarios without managing external user accounts + +Negative: +- Test authentication handlers bypass production authentication logic, potentially missing authentication-layer bugs +- Divergence between test and production authentication schemes may mask integration issues with real identity providers +- Test claims must be manually synchronized with production claim requirements as authorization policies evolve +- Additional test infrastructure code increases maintenance burden for authentication configuration + +## Alternatives + +- Use production authentication schemes with test identity provider instances (rejected) + Rejected because: Requires network-accessible test identity providers, increasing test infrastructure complexity and execution time while introducing external dependencies that reduce test reliability + When valid: When integration tests must validate production authentication flows including token validation, claim transformation, and identity provider protocol compliance +- Mock authentication middleware entirely and bypass AddAuthentication() (rejected) + Rejected because: Bypassing authentication middleware prevents testing authorization policies and claim-based authorization logic that depends on the ASP.NET Core authentication pipeline + When valid: When testing components that do not depend on authentication or authorization middleware +- Use anonymous authentication with authorization policy bypass (rejected) + Rejected because: Disabling authorization policies in tests creates divergence from production behavior and fails to validate authorization enforcement + When valid: When testing public endpoints that do not require authentication + +## Risks + +- Test authentication handlers may not accurately represent production authentication behavior, leading to authorization bugs that pass integration tests but fail in production + Mitigation: Maintain separate end-to-end tests with production authentication schemes against test identity providers; document differences between test and production authentication configuration + Owner: engineering team +- Test claims may become stale as production authorization policies evolve, causing tests to pass with insufficient claim sets + Mitigation: Review test authentication handlers when authorization policies change; implement shared claim validation logic between test and production code + Owner: engineering team +- Test authentication schemes may be accidentally deployed to production environments if configuration is not properly isolated + Mitigation: Use environment-specific configuration to ensure test authentication schemes are only registered in test environments; implement deployment validation to detect test authentication configuration in production + Owner: engineering team + +## Implementation Notes + +- Create test authentication handlers by extending AuthenticationHandler with constructor parameters for IOptionsMonitor, ILoggerFactory, UrlEncoder, and ISystemClock +- Override HandleAuthenticateAsync() to return AuthenticateResult.Success() with a ClaimsIdentity containing test claims (e.g., ClaimTypes.Name, organization identifiers) +- Register test authentication schemes using AddAuthentication("Test") in test startup or factory classes, ensuring the scheme name matches the identity scheme name in the ClaimsIdentity +- Configure authorization policies after authentication registration to ensure policies can evaluate claims provided by test authentication handlers + +## Continuation Context + + +Verify commands: +- grep -r "AddAuthentication" --include="*Test*.cs" --include="*Factory*.cs" | grep -v "//" +- grep -r "AuthenticationHandler" --include="*Test*.cs" | grep -v "//" +- grep -r "HandleAuthenticateAsync" --include="*Test*.cs" | grep -v "//" +- grep -r "AuthenticateResult.Success" --include="*Test*.cs" | grep -v "//" + +Accept when: +- Test projects contain classes extending AuthenticationHandler with HandleAuthenticateAsync() implementations +- Test startup or factory classes call AddAuthentication() to register authentication schemes +- Test authentication handlers return AuthenticateResult.Success() with ClaimsPrincipal containing test-appropriate claims + +## Enforcement + +- Verified by: Code review of test authentication handler implementations +- Verified by: Grep-based verification commands in CI pipeline to detect AddAuthentication() and AuthenticationHandler usage patterns +- Verified by: Integration test execution validates that authentication middleware is properly configured +- Violation handling: Integration tests that bypass authentication middleware or use production authentication schemes are flagged during code review +- Violation handling: CI pipeline fails if test authentication handlers are detected in production code paths +- Violation handling: Test failures indicating authentication or authorization issues trigger review of test authentication configuration +- Exception process: End-to-end tests requiring production authentication schemes may use real identity providers with documented justification +- Exception process: Public endpoint tests may omit authentication configuration when endpoints do not require authentication +- Exception process: Exceptions require approval from technical lead with documentation of alternative approach and rationale \ No newline at end of file diff --git a/docs/adr/f9a4858e-ea4a-426c-bb8e-6fc3a10fb197-adopt-api-key-authentication-scheme-for-scim-service-endpoints-scim-service-endpoints.md b/docs/adr/f9a4858e-ea4a-426c-bb8e-6fc3a10fb197-adopt-api-key-authentication-scheme-for-scim-service-endpoints-scim-service-endpoints.md new file mode 100644 index 000000000000..0c5735853e8c --- /dev/null +++ b/docs/adr/f9a4858e-ea4a-426c-bb8e-6fc3a10fb197-adopt-api-key-authentication-scheme-for-scim-service-endpoints-scim-service-endpoints.md @@ -0,0 +1,125 @@ +# Adopt API Key Authentication Scheme for SCIM Service Endpoints: Scim Service Endpoints + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The SCIM service requires authentication for API endpoints that provision and manage user and group resources across organizational boundaries +- ASP.NET Core authentication middleware provides extensible authentication handler infrastructure through AddAuthentication and custom scheme registration +- The codebase demonstrates two authentication patterns: ApiKeyAuthenticationOptions.DefaultScheme in production (Startup.cs) and a test-specific TestAuthHandler with claims-based identity in integration tests (ScimApplicationFactory.cs) +- Authorization policies enforce scope-based access control requiring authenticated users with 'api.scim' scope claims, indicating token-based authentication flows +- The System.Security.Claims namespace and ClaimsIdentity usage indicate claims-based authentication is the underlying identity model + +## Problem Statement + +SCIM endpoints expose sensitive organizational user and group provisioning operations that require secure authentication mechanisms to prevent unauthorized access, while maintaining compatibility with SCIM client implementations and supporting both production API key schemes and test harness authentication for integration testing. + +## Decision + +1. MUST: SCIM service endpoints MUST register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme as the primary authentication scheme + +## Policy Block + +- MUST SCIM service endpoints MUST register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme as the primary authentication scheme + +In scope: +- All SCIM v2 API endpoints under /v2/{organizationId}/groups and /v2/{organizationId}/users routes +- ApiKeyAuthenticationHandler and ApiKeyAuthenticationOptions implementations +- Authorization policies named 'Scim' with scope-based claim requirements +- Integration test authentication handlers inheriting from AuthenticationHandler +- ASP.NET Core authentication and authorization middleware configuration in Startup.ConfigureServices and Configure methods + +Out of scope: +- Non-SCIM API endpoints or services outside the bitwarden_license/src/Scim and bitwarden_license/test/Scim.IntegrationTest namespaces +- Frontend authentication flows or browser-based authentication mechanisms +- Database-level access control or row-level security policies +- OAuth2 authorization server implementation details beyond scope claim validation +- Network-level authentication such as mutual TLS or API gateway authentication + +Exceptions: +- EXC-001: Integration test environments require deterministic authentication without external credential validation + +## Rationale + +- The evidence shows consistent use of AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme across production code and custom TestAuthHandler in test code, indicating a deliberate authentication architecture pattern +- Claims-based authentication using System.Security.Claims provides standardized identity representation compatible with ASP.NET Core authorization policies and JWT scope validation +- The authorization policy requiring 'api.scim' scope claim indicates token-based authentication flows where API keys or tokens carry scope information for fine-grained access control +- Separation of test authentication handlers allows integration tests to simulate authenticated requests without external identity providers while maintaining the same authorization policy enforcement + +## Consequences + +Positive: +- Standardized authentication handler pattern enables consistent security enforcement across all SCIM endpoints with centralized authentication logic +- Claims-based identity model provides extensible authentication that can accommodate multiple claim types for organizational context and role-based access +- Test authentication handlers enable comprehensive integration testing of authorization policies without dependency on external authentication infrastructure +- Scope-based authorization policies provide fine-grained access control aligned with OAuth2 standards and SCIM protocol security requirements + +Negative: +- Custom authentication handler implementation requires maintenance of authentication logic separate from standard ASP.NET Core identity providers +- Test authentication handlers that bypass credential validation introduce risk if accidentally deployed to production environments +- API key authentication scheme may require additional token validation logic not evident in the provided code snippets +- Claims-based authentication adds complexity to the authentication pipeline compared to simpler authentication schemes without scope validation + +## Alternatives + +- Use ASP.NET Core Identity with cookie-based authentication for SCIM endpoints (rejected) + Rejected because: Cookie-based authentication is incompatible with SCIM client implementations that expect token-based or API key authentication for machine-to-machine communication + When valid: Browser-based administrative interfaces where session management is appropriate +- Implement JWT bearer token authentication without custom authentication handlers (rejected) + Rejected because: Evidence shows explicit use of ApiKeyAuthenticationOptions.DefaultScheme indicating API key scheme is preferred over standard JWT bearer authentication + When valid: Services that exclusively use OAuth2 JWT tokens without API key support requirements +- Use basic authentication with username and password for SCIM endpoints (rejected) + Rejected because: Basic authentication lacks scope-based authorization capabilities required by the 'api.scim' scope claim enforcement in authorization policies + When valid: Legacy systems with simple authentication requirements without fine-grained scope validation + +## Risks + +- Test authentication handlers may be accidentally included in production builds if assembly references are not properly isolated + Mitigation: Enforce build-time assembly separation between test and production code, implement deployment validation checks that verify test authentication schemes are not registered in production configuration + Owner: Platform Security Team +- API key authentication scheme implementation details are not visible in evidence, potentially hiding credential validation vulnerabilities + Mitigation: Conduct security review of ApiKeyAuthenticationHandler implementation to verify proper key validation, rate limiting, and secure key storage practices + Owner: Security Engineering Team +- Authorization policy requiring 'api.scim' scope may be bypassed if authentication handler does not properly validate and populate scope claims + Mitigation: Implement integration tests that verify unauthorized requests without proper scope claims are rejected, add monitoring for authentication failures and authorization policy violations + Owner: SCIM Service Team + +## Implementation Notes + +- Register authentication middleware before authorization middleware in Startup.Configure using app.UseAuthentication() followed by app.UseAuthorization() +- Ensure ApiKeyAuthenticationHandler validates API keys against secure storage and populates ClaimsPrincipal with required scope claims including 'api.scim' +- Implement test authentication handlers in separate test assemblies with clear naming conventions (e.g., TestAuthHandler) to prevent production deployment +- Configure authorization policies in Startup.ConfigureServices using AddAuthorization with policy.RequireAuthenticatedUser() and policy.RequireClaim(JwtClaimTypes.Scope, 'api.scim') +- Include organizational context claims (e.g., 'orgadmin' with organization ID) in authentication tickets to support multi-tenant authorization logic + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthentication.*ApiKeyAuthenticationOptions' bitwarden_license/src/Scim/ +- grep -r 'AddAuthorization.*api\.scim' bitwarden_license/src/Scim/ +- grep -r 'class.*AuthHandler.*:.*AuthenticationHandler' bitwarden_license/test/ +- dotnet test --filter 'FullyQualifiedName~Scim.IntegrationTest' --no-build + +Accept when: +- All SCIM service Startup.cs files register authentication using AddAuthentication with ApiKeyAuthenticationOptions.DefaultScheme +- Authorization policies named 'Scim' require authenticated users and enforce 'api.scim' scope claims +- Test authentication handlers are isolated to test assemblies and inherit from AuthenticationHandler with proper claims population +- Integration tests successfully authenticate requests and verify authorization policy enforcement + +## Enforcement + +- Verified by: Code review verification that Startup.cs authentication configuration follows the prescribed pattern +- Verified by: Static analysis scanning for authentication middleware registration order in ASP.NET Core pipeline +- Verified by: Integration test suite execution validating authentication and authorization behavior +- Verified by: Security audit of ApiKeyAuthenticationHandler implementation for proper credential validation +- Violation handling: Pull requests that modify authentication configuration without maintaining ApiKeyAuthenticationOptions.DefaultScheme are blocked pending security review +- Violation handling: Production deployments with test authentication handlers registered trigger automated rollback and incident response +- Violation handling: Authorization policy changes that weaken scope claim requirements require security team approval +- Violation handling: Authentication handler implementations that do not properly validate credentials are flagged in security scanning and require immediate remediation +- Exception process: Exception requests must document specific authentication requirements that cannot be met by the standard API key authentication scheme +- Exception process: Security team reviews exception requests to assess risk and approve alternative authentication mechanisms +- Exception process: Approved exceptions are documented in ADR amendments with explicit scope boundaries and sunset dates +- Exception process: Temporary exceptions for migration scenarios require migration plan with timeline and rollback procedures \ No newline at end of file diff --git a/docs/adr/fb740243-8248-4287-971c-36a708d8c36a-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-failures.md b/docs/adr/fb740243-8248-4287-971c-36a708d8c36a-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-failures.md new file mode 100644 index 000000000000..6c3c380fe8f0 --- /dev/null +++ b/docs/adr/fb740243-8248-4287-971c-36a708d8c36a-log-authorization-failures-with-structured-context-in-provider-and-admin-controllers-log-entries-failures.md @@ -0,0 +1,117 @@ +# Log Authorization Failures with Structured Context in Provider and Admin Controllers: Log Entries Failures + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Authorization-protected endpoints in ProvidersController and HomeController require structured logging to capture operational failures that occur after authorization succeeds but business logic fails +- The ProvidersController uses custom authorization requirements (ProviderUserRequirement, ProviderAdminRequirement) alongside the [Authorize] attribute, creating multiple authorization layers that need visibility +- Third-party service integration failures (e.g., Stripe billing sync) occur within authorized contexts and must be logged with sufficient context to correlate with authorization decisions +- The codebase uses Microsoft.Extensions.Logging.ILogger with structured logging patterns, injecting logger instances into controllers that handle sensitive provider and admin operations + +## Problem Statement + +When authorization succeeds but subsequent business logic or external service calls fail within authorized controller actions, operators need structured log entries that correlate the failure with the authorization context (user identity, resource ID, operation type) to diagnose security-relevant operational issues, audit authorization effectiveness, and troubleshoot integration failures without exposing sensitive data. + +## Decision + +1. MUST: Log entries for failures in authorized contexts MUST include structured parameters for resource identifiers (e.g., {ProviderId}, {UserId}) using named placeholders, not string interpolation + +## Policy Block + +- MUST Log entries for failures in authorized contexts MUST include structured parameters for resource identifiers (e.g., {ProviderId}, {UserId}) using named placeholders, not string interpolation + +In scope: +- All ASP.NET Core MVC controllers decorated with [Authorize] or custom authorization attributes +- Controller actions that invoke external services (billing, payment, notification) after authorization checks +- Admin and provider management endpoints handling sensitive resource operations +- Exception handlers and catch blocks within authorized action methods + +Out of scope: +- Anonymous endpoints decorated with [AllowAnonymous] +- Middleware-level authorization logging (handled by ASP.NET Core infrastructure) +- Client-side logging or browser console output +- Database audit tables or event sourcing logs (complementary but separate concern) + +Exceptions: +- EXC-001: High-frequency endpoints where structured logging would create excessive log volume + +## Rationale + +- The evidence shows ILogger and ILogger injected into controllers with [Authorize] attributes, demonstrating established structured logging infrastructure +- ProvidersController.Put method logs Stripe sync failures with structured {ProviderId} parameter after successful authorization and partial database update, showing the pattern of correlating authorization context with operational failures +- HomeController logs HTTP request failures with structured {RequestUri} parameter within authorized Index action, indicating consistent application of structured logging across authorization boundaries +- The pattern enables security teams to audit whether authorization decisions are followed by successful operations or if authorized users encounter systematic failures that might indicate privilege escalation attempts or misconfigured permissions + +## Consequences + +Positive: +- Operators can correlate authorization events with downstream failures using structured log queries (e.g., filter by ProviderId across authorization and business logic logs) +- Security audits can identify patterns where authorized users systematically fail operations, indicating potential permission boundary issues or missing authorization checks +- Troubleshooting external service integration failures becomes faster with resource context preserved from authorization through to failure point +- Structured logging enables automated alerting on authorization-related operational failures without manual log parsing + +Negative: +- Increased log volume from structured parameters may require log retention policy adjustments and storage capacity planning +- Developers must remember to add structured logging to all new authorized endpoints, creating maintenance burden +- Risk of accidentally logging sensitive data if developers use incorrect structured parameters or log entire request/response objects +- Performance overhead from logger allocation and structured parameter boxing in high-throughput authorized endpoints + +## Alternatives + +- Use middleware-level logging to capture all authorization outcomes without controller-specific logging (rejected) + Rejected because: Middleware cannot access business logic context (e.g., partial success states, external service failures) that occurs after authorization succeeds + When valid: Sufficient for pure authorization audit trails without operational failure correlation +- Implement aspect-oriented programming (AOP) to automatically inject logging around all [Authorize] methods (deferred) + Rejected because: Requires additional framework dependencies and may not capture nuanced partial failure states that need explicit logging + When valid: When standardizing cross-cutting concerns across large codebases with consistent authorization patterns +- Log only to database audit tables without structured application logging (rejected) + Rejected because: Database audit tables lack real-time alerting capabilities and cannot capture external service failures that don't result in database transactions + When valid: Compliance scenarios requiring immutable audit records with transactional consistency + +## Risks + +- Developers may inadvertently log sensitive data (tokens, passwords, PII) in structured parameters within authorized contexts + Mitigation: Implement code review checklist for authorization-related logging; use static analysis tools to detect common sensitive parameter names; provide logging helper methods that sanitize inputs + Owner: Security team and engineering leads +- High-volume authorized endpoints may generate excessive logs, increasing storage costs and reducing signal-to-noise ratio + Mitigation: Implement log sampling for high-frequency endpoints; use log levels appropriately (Error for failures, Debug for success); configure log aggregation with retention policies + Owner: Operations team +- Inconsistent logging patterns across controllers may create gaps in authorization audit trails + Mitigation: Create base controller class with logging helpers; document logging patterns in architecture guidelines; include logging verification in pull request templates + Owner: Engineering team + +## Implementation Notes + +- Inject ILogger via constructor dependency injection in all controllers with [Authorize] attributes or custom authorization requirements +- Use LogError(exception, message, structuredParams) pattern for all catch blocks within authorized actions, ensuring exception object is first parameter +- Define structured parameter names as constants (e.g., const string ProviderIdParam = '{ProviderId}') to ensure consistency across log statements +- Review existing controllers (ProvidersController, HomeController) as reference implementations for structured logging patterns in authorized contexts +- Configure log sinks (Application Insights, Seq, ELK) to index structured parameters for efficient querying by resource identifiers + +## Continuation Context + + +Verify commands: +- grep -r "\[Authorize" src/ | xargs -I {} dirname {} | sort -u | xargs -I {} grep -L "ILogger<" {}/ +- grep -r "LogError" src/ --include="*Controller.cs" | grep -v "\{.*\}" | grep -v "@" +- grep -r "_logger\.Log" src/ --include="*Controller.cs" -A 2 | grep -E "(Password|Token|Secret|Key|Credit)" + +Accept when: +- All controllers with [Authorize] attributes inject ILogger and have no grep matches for missing logger injection +- All LogError calls in controller files use structured parameters (contain curly braces) with no plain string concatenation matches +- No log statements in controllers contain sensitive parameter names (Password, Token, Secret, Key, Credit) in structured parameters + +## Enforcement + +- Verified by: Code review checklist requiring verification of ILogger injection and structured logging in all new authorized endpoints +- Verified by: Static analysis rules detecting LogError calls without structured parameters in controller files +- Verified by: CI pipeline grep checks for sensitive parameter names in logging statements (fails build on match) +- Violation handling: Pull requests with authorized endpoints lacking structured logging are blocked until logging is added +- Violation handling: Static analysis violations trigger build warnings that must be resolved or explicitly suppressed with justification +- Violation handling: Post-deployment log audits identify controllers with authorization but no error logging; tracked as technical debt tickets +- Exception process: High-frequency endpoints may request exception via architecture review board with documented sampling strategy +- Exception process: Exception requests must include alternative monitoring approach (metrics, health checks, database audit) +- Exception process: Approved exceptions documented in controller comments with EXC-001 reference and expiration date for re-review \ No newline at end of file diff --git a/docs/adr/fbc0365b-bba7-4bc2-b4bb-0667cfe7b8d6-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-key-generation.md b/docs/adr/fbc0365b-bba7-4bc2-b4bb-0667cfe7b8d6-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-key-generation.md new file mode 100644 index 000000000000..32d0c87a7eae --- /dev/null +++ b/docs/adr/fbc0365b-bba7-4bc2-b4bb-0667cfe7b8d6-adopt-ffi-safe-c-string-handling-with-explicit-ownership-transfer-for-rust-sdk-cryptographic-key-generation.md @@ -0,0 +1,121 @@ +# Adopt FFI-Safe C String Handling with Explicit Ownership Transfer for Rust SDK: Cryptographic Key Generation + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- The Rust SDK exposes cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) through a C FFI boundary, requiring safe marshaling of string data between Rust and C memory models +- FFI boundaries introduce memory safety risks when transferring ownership of heap-allocated strings, particularly when C callers must deallocate Rust-allocated memory +- The codebase uses std::ffi types (c_char, CStr, CString) to handle string conversions at the FFI boundary, with an explicit free_c_string function to manage deallocation +- Cryptographic operations involving cipher objects, RSA keys (via RSA_POOL), and SymmetricCryptoKey require secure handling to prevent memory leaks or use-after-free vulnerabilities +- The pattern appears in util/RustSdk/rust/src/lib.rs with public API contracts that expose cryptographic primitives to C consumers + +## Problem Statement + +When exposing Rust cryptographic APIs through C FFI, improper string handling can lead to memory safety violations including leaks, double-frees, or use-after-free bugs. The ownership transfer semantics between Rust's memory model and C's manual memory management must be explicitly defined and enforced to prevent security vulnerabilities in cryptographic key material handling. + +## Decision + +1. MUST: Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) MUST validate all input strings before processing + +## Policy Block + +- MUST Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) MUST validate all input strings before processing + +In scope: +- All public FFI functions in util/RustSdk/rust/src/lib.rs +- Cryptographic key generation and management functions exposed to C +- String parameters and return values crossing the Rust/C FFI boundary +- Memory deallocation functions for Rust-allocated resources + +Out of scope: +- Pure Rust APIs that do not cross FFI boundaries +- Internal string handling within Rust modules +- Non-cryptographic data structures +- Platform-specific FFI bindings outside the RustSdk module + +Exceptions: +- EXC-001: Static string literals that do not require deallocation + +## Rationale + +- The evidence shows explicit use of std::ffi::{c_char, CStr, CString} types alongside a free_c_string function, indicating intentional ownership transfer semantics at the FFI boundary +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) handle sensitive data that requires secure memory management to prevent information leakage +- The presence of bitwarden_crypto::SymmetricCryptoKey and RSA_POOL demonstrates cryptographic operations where memory safety violations could compromise security guarantees +- The pattern of public API contracts combined with FFI types establishes a consistent approach to safe interoperability between Rust's ownership model and C's manual memory management + +## Consequences + +Positive: +- Prevents memory leaks and use-after-free vulnerabilities in cryptographic key handling across language boundaries +- Provides explicit ownership transfer semantics that C callers can reason about and implement correctly +- Enables safe exposure of Rust cryptographic primitives to legacy C codebases without compromising memory safety +- Establishes a consistent pattern for FFI string handling that can be audited and verified + +Negative: +- Requires C callers to understand and correctly implement Rust's ownership model through manual free_c_string calls +- Adds cognitive overhead and potential for misuse if C callers forget to deallocate strings +- Increases API surface area with additional memory management functions +- May introduce performance overhead from string conversions at the FFI boundary + +## Alternatives + +- Use caller-allocated buffers where C provides pre-allocated memory and Rust writes into it (rejected) + Rejected because: Requires C callers to predict buffer sizes for cryptographic outputs, leading to either buffer overflows or excessive memory allocation. The variable-length nature of key material makes this approach error-prone. + When valid: When output sizes are fixed and known at compile time +- Return all strings through callback functions that process data without transferring ownership (rejected) + Rejected because: Adds complexity to the API and prevents C callers from storing key material for later use. Callbacks introduce additional FFI overhead and complicate error handling. + When valid: When data should not persist beyond the function call scope +- Use reference-counted smart pointers (Arc) exposed through opaque handles (deferred) + Rejected because: Requires more complex FFI infrastructure with retain/release functions. May be considered for future iterations if resource tracking becomes necessary. + When valid: When multiple C components need shared ownership of Rust-allocated resources + +## Risks + +- C callers may forget to call free_c_string, causing memory leaks of sensitive cryptographic material + Mitigation: Provide comprehensive documentation, examples, and consider adding leak detection in test builds. Document the free_c_string requirement prominently in all FFI function documentation. + Owner: Security team and SDK maintainers +- Double-free vulnerabilities if C callers deallocate strings multiple times or use platform free() instead of free_c_string + Mitigation: Implement debug-mode tracking using HashSet to detect double-free attempts. Clearly document that platform free() must not be used on Rust-allocated strings. + Owner: Engineering team +- Use-after-free if C callers continue using string pointers after calling free_c_string + Mitigation: Document lifetime requirements clearly. Consider adding sanitizer builds to CI pipeline to detect use-after-free in integration tests. + Owner: QA and security teams + +## Implementation Notes + +- All public FFI functions returning strings must use CString::into_raw() to transfer ownership and document the requirement to call free_c_string +- The free_c_string function must use CString::from_raw() to reclaim ownership before deallocation, ensuring proper cleanup +- Input validation should check for null pointers using .is_null() before dereferencing c_char pointers from C +- Consider wrapping FFI functions in a safer C++ or higher-level wrapper library that automates memory management using RAII patterns +- Document the memory ownership contract in header files and API documentation, including examples of correct usage + +## Continuation Context + + +Verify commands: +- grep -r 'CString::into_raw\|CString::from_raw' util/RustSdk/rust/src/ | wc -l +- grep -r 'pub.*extern "C".*c_char' util/RustSdk/rust/src/lib.rs +- grep -r 'free_c_string' util/RustSdk/rust/src/lib.rs + +Accept when: +- All public FFI functions returning strings use CString::into_raw() and document free_c_string requirement +- A free_c_string function exists and is exported in the public API +- Input validation checks for null pointers before dereferencing c_char parameters +- Documentation includes examples of correct string ownership transfer and deallocation + +## Enforcement + +- Verified by: Code review checklist requiring verification of CString usage patterns in FFI functions +- Verified by: Static analysis with clippy lints for FFI safety (clippy::not_unsafe_ptr_arg_deref) +- Verified by: Integration tests with memory sanitizers (AddressSanitizer, LeakSanitizer) in CI pipeline +- Verified by: Security audit of FFI boundary code during release cycles +- Violation handling: CI build fails if FFI functions return raw pointers without corresponding deallocation functions +- Violation handling: Code review blocks merge if FFI string handling lacks proper documentation +- Violation handling: Memory sanitizer failures in CI require immediate fix before merge +- Violation handling: Security team escalation for violations in cryptographic key handling code +- Exception process: Document exception rationale in code comments with reference to EXC-001 for static string literals +- Exception process: Obtain security team approval for any FFI patterns deviating from CString/CStr usage +- Exception process: Record exceptions in security review log with justification and compensating controls \ No newline at end of file diff --git a/docs/adr/fbefe97a-b42f-4765-86e9-e0fa40079305-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-public-ffi-functions.md b/docs/adr/fbefe97a-b42f-4765-86e9-e0fa40079305-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-public-ffi-functions.md new file mode 100644 index 000000000000..006ec27e5f0b --- /dev/null +++ b/docs/adr/fbefe97a-b42f-4765-86e9-e0fa40079305-validate-c-ffi-string-inputs-using-rust-cstr-cstring-conversion-public-ffi-functions.md @@ -0,0 +1,123 @@ +# Validate C FFI String Inputs Using Rust CStr/CString Conversion: Public Ffi Functions + +Status: proposed +Date: 2025-01-20 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is active for all Rust FFI boundary code that accepts C-style string pointers (c_char) from external callers. + +## Context + +- The RustSdk exposes public FFI functions (generate_user_keys, generate_organization_keys, generate_user_organization_key, free_c_string) that accept raw C-style string pointers from external callers across language boundaries +- FFI boundaries introduce memory safety risks where untrusted or malformed input can cause undefined behavior, including null pointer dereferences, invalid UTF-8 sequences, or missing null terminators +- The codebase uses std::ffi::{c_char, CStr, CString} types consistently across util/RustSdk/rust/src/lib.rs and util/RustSdk/rust/src/rsa_keys.rs to handle C string conversion +- Cryptographic operations (cipher, rsa_keys, RSA_POOL, SymmetricCryptoKey) require validated input to prevent security vulnerabilities from propagating into key generation and encryption workflows +- The pattern appears in 2 files with 90.50% significance, indicating systematic adoption of defensive input validation at the FFI boundary layer + +## Problem Statement + +External callers invoking Rust FFI functions may pass malformed, null, or improperly terminated C string pointers that bypass Rust's memory safety guarantees. Without explicit validation using CStr conversion, these inputs can cause crashes, undefined behavior, or security vulnerabilities in downstream cryptographic operations. The FFI boundary requires a standardized approach to safely convert and validate C string inputs before processing. + +## Decision + +1. MUST: All public FFI functions accepting c_char pointers MUST convert them to CStr using CStr::from_ptr before accessing the underlying data + +## Policy Block + +- MUST All public FFI functions accepting c_char pointers MUST convert them to CStr using CStr::from_ptr before accessing the underlying data + +In scope: +- All public extern "C" functions in util/RustSdk/rust/src/lib.rs accepting c_char pointer parameters +- FFI helper functions in util/RustSdk/rust/src/rsa_keys.rs that process C string inputs +- String return values from Rust FFI functions that cross back to C callers +- Cryptographic key generation functions (generate_user_keys, generate_organization_keys, generate_user_organization_key) receiving string parameters + +Out of scope: +- Internal Rust functions that do not cross FFI boundaries and use native String/&str types +- Pure Rust modules that do not expose extern "C" interfaces +- Test code using Rust-native string literals that never convert to c_char pointers +- FFI functions accepting non-string primitive types (integers, booleans, raw byte buffers) + +Exceptions: +- EXC-001: FFI function accepts a pre-validated byte buffer with explicit length parameter instead of null-terminated c_char pointer +- EXC-002: Performance-critical FFI path requires zero-copy string access with caller-guaranteed validity + +## Rationale + +- The evidence shows systematic use of std::ffi::{c_char, CStr, CString} across 2 files (lib.rs, rsa_keys.rs) with 90.50% significance, indicating an established pattern for FFI string handling +- CStr::from_ptr provides memory-safe conversion from C strings by validating null termination, while CString::into_raw enables safe ownership transfer back to C callers with explicit free_c_string cleanup +- Cryptographic operations detected in the evidence (cipher, rsa_keys, SymmetricCryptoKey, RSA_POOL) require validated inputs to prevent security vulnerabilities from malformed data propagating into key generation workflows +- The pattern aligns with Rust FFI best practices for defensive programming at trust boundaries, where external callers may provide malicious or malformed input that bypasses Rust's compile-time safety guarantees + +## Consequences + +Positive: +- Prevents null pointer dereferences, buffer overruns, and undefined behavior from malformed C string inputs at the FFI boundary +- Enables explicit UTF-8 validation and error handling before cryptographic operations, reducing attack surface for key generation functions +- Provides clear ownership semantics for string memory management across language boundaries using CString::into_raw and free_c_string +- Maintains Rust memory safety guarantees even when interfacing with unsafe C code by enforcing validation at the boundary layer + +Negative: +- Adds runtime overhead for CStr validation and UTF-8 checking on every FFI string input, potentially impacting high-frequency API calls +- Requires explicit error handling and propagation for invalid string inputs, increasing FFI function complexity and caller error-handling burden +- CString::into_raw transfers ownership to C caller, requiring disciplined memory management and correct free_c_string invocation to avoid leaks +- Test fixtures using hardcoded _FAKE_RSA_KEY_* constants may obscure real-world FFI validation behavior if not supplemented with integration tests using actual C callers + +## Alternatives + +- Accept raw byte buffers with explicit length parameters instead of null-terminated c_char pointers (rejected) + Rejected because: Requires changing all FFI function signatures and breaks compatibility with existing C callers expecting null-terminated strings. Evidence shows established use of c_char pointers across public API functions (generate_user_keys, generate_organization_keys, generate_user_organization_key). + When valid: Valid for new FFI APIs designed from scratch where caller compatibility is not a constraint and binary data (non-UTF-8) must be supported +- Trust C callers to provide valid strings and skip CStr validation for performance (rejected) + Rejected because: Violates Rust safety principles at trust boundaries and exposes cryptographic operations (cipher, rsa_keys, key generation) to undefined behavior from malformed inputs. The 90.50% pattern significance indicates systematic validation is already adopted. + When valid: Never valid for public FFI APIs; only acceptable for internal FFI boundaries with formal caller contracts and extensive integration testing +- Use higher-level FFI binding generators (cbindgen, cxx) to automate string conversion (deferred) + Rejected because: Not rejected, but evidence shows manual CStr/CString usage is already established. Migration to binding generators would require significant refactoring of existing FFI surface. + When valid: Valid for future FFI expansion or major refactoring efforts where automated binding generation can reduce manual unsafe code and improve maintainability + +## Risks + +- CString::into_raw memory leaks if C callers fail to invoke free_c_string on returned strings + Mitigation: Document free_c_string requirement in all FFI function headers. Add runtime leak detection in test builds. Consider providing language-specific wrapper libraries (Python, C++) that automate cleanup. + Owner: FFI API team +- Performance degradation from repeated CStr validation and UTF-8 checking in high-frequency FFI calls + Mitigation: Profile FFI boundary overhead in realistic workloads. For performance-critical paths, document exception process (EXC-002) requiring explicit unsafe blocks with caller contracts and security review approval. + Owner: Performance engineering team +- Inconsistent error handling across FFI functions may confuse C callers or hide validation failures + Mitigation: Standardize FFI error codes and return conventions (e.g., null pointer for errors, errno-style codes). Document error semantics in FFI header files. Add integration tests verifying error propagation from C caller perspective. + Owner: API design team + +## Implementation Notes + +- Wrap all c_char pointer parameters in null checks before calling CStr::from_ptr to prevent undefined behavior from null pointers +- Use CStr::to_str() for UTF-8 validation and handle Err results by returning error codes to C callers rather than panicking +- For functions returning strings, use CString::new().unwrap().into_raw() and document that callers must invoke free_c_string to avoid memory leaks +- Add unit tests with invalid inputs (null pointers, non-UTF-8 sequences, missing null terminators) to verify FFI boundary validation behavior +- Document string encoding requirements (UTF-8, null-terminated) in FFI function comments and generated C header files + +## Continuation Context + + +Verify commands: +- grep -r 'extern "C"' util/RustSdk/rust/src/ | xargs grep -L 'CStr::from_ptr' # Should return empty (all FFI functions use CStr) +- grep -r 'CString::into_raw' util/RustSdk/rust/src/ | wc -l # Should match count of string-returning FFI functions +- cargo test --package rust-sdk -- ffi # Run FFI-specific tests including invalid input cases + +Accept when: +- All public extern "C" functions accepting c_char pointers perform CStr::from_ptr conversion with null checks before accessing data +- FFI functions returning strings use CString::into_raw and provide corresponding free_c_string cleanup function +- Test suite includes cases for null pointers, invalid UTF-8, and missing null terminators with verified error handling + +## Enforcement + +- Verified by: Automated CI checks using grep patterns to verify CStr usage in all extern "C" functions accepting c_char pointers +- Verified by: Code review checklist requiring FFI boundary validation review for any new or modified extern "C" functions +- Verified by: Cargo clippy lints for unsafe FFI patterns (clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref) +- Violation handling: CI build failure if grep verification commands detect extern "C" functions missing CStr conversion +- Violation handling: Code review rejection for FFI changes lacking null checks, UTF-8 validation, or error handling +- Violation handling: Security incident response for production issues traced to unvalidated FFI inputs, requiring immediate patch and retrospective +- Exception process: Submit exception request (EXC-001 or EXC-002) with justification to architecture review board +- Exception process: Obtain approval from security team lead for cryptographic FFI paths or performance engineering team for performance-critical exceptions +- Exception process: Document approved exceptions in FFI function comments with explicit unsafe block justifications and caller contract requirements \ No newline at end of file diff --git a/docs/adr/fcbd71ee-73d7-435c-983b-76fc42f54448-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-policies-registered.md b/docs/adr/fcbd71ee-73d7-435c-983b-76fc42f54448-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-policies-registered.md new file mode 100644 index 000000000000..f76e88b6d6f4 --- /dev/null +++ b/docs/adr/fcbd71ee-73d7-435c-983b-76fc42f54448-enforce-authorization-via-policy-based-configuration-in-scim-services-authorization-policies-registered.md @@ -0,0 +1,121 @@ +# Enforce Authorization via Policy-Based Configuration in SCIM Services: Authorization Policies Registered + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all SCIM service implementations and authorization enforcement points within the domain modeling layer. + +## Context + +- The SCIM integration services require authorization enforcement to control access to organization-scoped resources including users and groups +- Authorization policies are configured at application startup using AddAuthorization with named policy definitions that specify authentication requirements and claim-based rules +- The Scim policy enforces authenticated user access and requires the 'api.scim' scope claim from JwtClaimTypes to gate API operations +- Test environments use simplified authorization policies with RequireAssertion(a => true) to enable integration testing without full authentication infrastructure +- Authorization enforcement points are established in the middleware pipeline between authentication and controller execution to validate policy compliance before domain operations + +## Problem Statement + +SCIM API endpoints expose organization-sensitive operations for user and group provisioning that require consistent authorization enforcement across production and test environments, necessitating a declarative policy-based approach that separates authorization logic from domain business logic while maintaining testability. + +## Decision + +1. MUST: Authorization policies MUST be registered using services.AddAuthorization during application startup in the ConfigureServices method + +## Policy Block + +- MUST Authorization policies MUST be registered using services.AddAuthorization during application startup in the ConfigureServices method + +In scope: +- All SCIM API endpoints under /v2/{organizationId}/users and /v2/{organizationId}/groups routes +- Services implementing IScimContext and ICurrentContext interfaces +- Controllers decorated with authorization policy attributes +- Middleware pipeline components between UseAuthentication and UseAuthorization + +Out of scope: +- Health check endpoints and diagnostic routes +- Static file serving and public documentation endpoints +- Internal service-to-service communication not exposed via SCIM API +- Background job processing and scheduled tasks + +Exceptions: +- EXC-001: Integration test environments require simplified authorization for automated testing + +## Rationale + +- Evidence shows consistent use of AddAuthorization configuration in both production (Startup.cs) and test (ScimApplicationFactory.cs) contexts with named 'Scim' policies +- The pattern separates authorization concerns from domain modeling by establishing enforcement points in the middleware pipeline rather than embedding checks in business logic +- Claim-based authorization using JwtClaimTypes.Scope enables fine-grained access control aligned with OAuth2/OIDC standards for API scoping +- Test environment flexibility is achieved through policy configuration variance while maintaining the same enforcement point architecture + +## Consequences + +Positive: +- Authorization logic is centralized in startup configuration, improving maintainability and reducing duplication across controllers +- Policy-based enforcement enables consistent security posture across all SCIM endpoints without per-method authorization code +- Test environments can override authorization policies without modifying production code paths +- Claim-based policies integrate naturally with JWT authentication schemes and identity providers + +Negative: +- Policy configuration is separated from endpoint definitions, requiring developers to understand the relationship between named policies and their enforcement +- Test policy simplification (RequireAssertion(a => true)) may mask authorization bugs that only surface in production environments +- Adding new authorization requirements requires modifying centralized startup configuration rather than localized controller attributes +- Debugging authorization failures requires understanding the middleware pipeline execution order and policy evaluation logic + +## Alternatives + +- Implement authorization checks inline within domain service methods using imperative guard clauses (rejected) + Rejected because: Inline checks couple authorization logic to business logic, reducing testability and increasing duplication across service methods + When valid: May be appropriate for complex authorization rules that depend on domain state not available at the HTTP request boundary +- Use controller-level [Authorize] attributes with policy names instead of centralized middleware configuration (rejected) + Rejected because: Attribute-based authorization still requires centralized policy definition but distributes enforcement point declarations across controllers, reducing visibility + When valid: Suitable for applications with heterogeneous authorization requirements across different controller groups +- Implement custom authorization handlers with resource-based authorization for fine-grained control (deferred) + Rejected because: Current evidence shows scope-based authorization is sufficient; resource-based handlers add complexity without demonstrated need + When valid: Should be reconsidered if authorization decisions require access to domain entities or organization-specific rules + +## Risks + +- Test policy simplification may allow unauthorized access patterns to pass integration tests but fail in production + Mitigation: Implement separate authorization-focused test suites that validate policy enforcement with realistic authentication tokens and claims + Owner: QA and security testing teams +- Centralized policy configuration creates a single point of failure where misconfiguration affects all SCIM endpoints + Mitigation: Add startup validation tests that verify policy registration and claim requirements match security specifications + Owner: Platform engineering team +- Middleware ordering errors (e.g., UseAuthorization before UseAuthentication) will cause authorization to fail silently or incorrectly + Mitigation: Document required middleware ordering in startup configuration and add runtime diagnostics to detect misconfiguration + Owner: Engineering team + +## Implementation Notes + +- Register authentication schemes before calling AddAuthorization to ensure authentication handlers are available for policy evaluation +- Place app.UseAuthentication() before app.UseAuthorization() in the Configure method to ensure claims are populated before policy evaluation +- Use named policies ('Scim') consistently across startup configuration and controller authorization attributes to maintain enforcement point clarity +- Document test policy deviations explicitly in test factory classes to prevent confusion about authorization behavior differences between environments + +## Continuation Context + + +Verify commands: +- grep -r 'AddAuthorization' --include='*.cs' | grep -E 'config\.AddPolicy\("Scim"' +- grep -r 'RequireClaim.*api\.scim' --include='*.cs' +- grep -r 'UseAuthorization\(\)' --include='*.cs' | grep -B5 'UseAuthentication()' | grep -A5 'UseAuthorization()' + +Accept when: +- All SCIM service startup classes contain AddAuthorization configuration with a named 'Scim' policy +- Production Scim policies include RequireAuthenticatedUser and RequireClaim for 'api.scim' scope +- Middleware pipeline ordering shows UseAuthentication called before UseAuthorization in all Configure methods + +## Enforcement + +- Verified by: Code review verification of startup configuration in ConfigureServices and Configure methods +- Verified by: Integration tests validating authorization policy enforcement for SCIM endpoints +- Verified by: Static analysis scanning for authorization policy registration patterns +- Violation handling: Pull requests missing authorization policy configuration for new SCIM endpoints are blocked +- Violation handling: Runtime authorization failures return 401 Unauthorized or 403 Forbidden responses with diagnostic logging +- Violation handling: Security audits flag endpoints lacking policy enforcement point coverage +- Exception process: Exception requests must document the specific endpoint and justification for alternative authorization approach +- Exception process: Security team review and approval required for any deviation from policy-based enforcement +- Exception process: Approved exceptions must be documented in code comments and tracked in security review logs \ No newline at end of file diff --git a/docs/adr/fcd63002-33ef-4693-9995-de547f45589e-enforce-authorization-service-pattern-for-access-control-decisions-custom-authorization-requirements.md b/docs/adr/fcd63002-33ef-4693-9995-de547f45589e-enforce-authorization-service-pattern-for-access-control-decisions-custom-authorization-requirements.md new file mode 100644 index 000000000000..65c05f95d110 --- /dev/null +++ b/docs/adr/fcd63002-33ef-4693-9995-de547f45589e-enforce-authorization-service-pattern-for-access-control-decisions-custom-authorization-requirements.md @@ -0,0 +1,126 @@ +# Enforce Authorization Service Pattern for Access Control Decisions: Custom Authorization Requirements + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all authorization enforcement points in API controllers and application services. + +## Context + +- The codebase implements authorization enforcement through ASP.NET Core's IAuthorizationService, requiring explicit authorization checks at controller action boundaries +- Authorization decisions are separated from business logic through policy-based authorization using AddAuthorization configuration and custom requirement handlers +- Multiple authorization requirements exist across the system including ManageUsersRequirement, ManageAccountRecoveryRequirement, MemberOrProviderRequirement, and custom authorization handlers +- Authorization enforcement points are distributed across API controllers handling organization user management, SCIM integration, and administrative operations +- The pattern coordinates authentication schemes (including test authentication for integration testing) with authorization policies to control access to protected resources + +## Problem Statement + +Without a consistent authorization enforcement pattern, access control decisions become scattered throughout business logic, making security policies difficult to audit, test, and maintain. The system needs a standardized approach to enforce authorization at API boundaries while keeping authorization logic separate from domain operations. + +## Decision + +1. SHOULD: Custom authorization requirements SHOULD implement IAuthorizationRequirement and be evaluated by corresponding AuthorizationHandler implementations + +## Policy Block + +- SHOULD Custom authorization requirements SHOULD implement IAuthorizationRequirement and be evaluated by corresponding AuthorizationHandler implementations + +In scope: +- All ASP.NET Core API controllers with [Authorize] attributes +- Controller actions handling organization user management operations +- SCIM integration endpoints requiring policy-based authorization +- Administrative console controllers managing access control +- Bulk operations affecting multiple protected resources + +Out of scope: +- Public API endpoints without authentication requirements +- Internal service-to-service calls within the same trust boundary +- Background jobs and scheduled tasks with system-level privileges +- Database-level access control and row-level security + +Exceptions: +- EXC-001: Integration test scenarios require bypassing authorization to test business logic in isolation +- EXC-002: Self-service operations where the user is operating on their own resources (e.g., RevokeSelfAsync) + +## Rationale + +- The pattern separates authorization concerns from business logic, enabling centralized security policy management and reducing the risk of authorization bypass vulnerabilities +- Policy-based authorization with IAuthorizationService provides a testable, composable approach to access control that can be verified independently of controller logic +- Evidence shows consistent usage across 2 files with 79.40% confidence, indicating an established architectural pattern for authorization enforcement in ASP.NET Core controllers +- The pattern enables fine-grained authorization decisions (e.g., BulkCollectionOperations.ModifyUserAccess) while maintaining a uniform enforcement mechanism across all protected endpoints + +## Consequences + +Positive: +- Authorization logic is centralized and reusable through policy-based requirements, reducing code duplication across controllers +- Security policies can be audited, tested, and modified independently of business logic implementation +- Authorization failures are handled consistently with appropriate HTTP status codes and error responses +- The pattern supports complex authorization scenarios including bulk operations, self-service actions, and resource-specific permissions + +Negative: +- Requires additional boilerplate code in controllers to inject IAuthorizationService and perform authorization checks before each protected operation +- Authorization logic is distributed between controller actions and separate authorization handler classes, requiring navigation across multiple files to understand complete access control rules +- Performance overhead from authorization service calls on every protected operation, though typically negligible compared to database operations +- Testing complexity increases as authorization handlers must be mocked or configured in test scenarios + +## Alternatives + +- Use attribute-based authorization exclusively with [Authorize(Policy = "PolicyName")] attributes on controller actions (rejected) + Rejected because: Attribute-based authorization alone cannot handle dynamic authorization decisions that depend on resource state (e.g., checking if a user can modify specific collections), requiring imperative authorization checks with IAuthorizationService + When valid: Suitable for simple role-based or policy-based authorization where decisions do not depend on runtime resource state +- Implement authorization logic directly in business service layer methods (rejected) + Rejected because: Mixing authorization with business logic violates separation of concerns, makes security policies harder to audit, and couples domain logic to authorization infrastructure + When valid: May be appropriate for domain-specific business rules that are distinct from access control policies +- Use resource-based authorization with IAuthorizationService.AuthorizeAsync(user, resource, requirement) pattern (accepted) + When valid: This is the implemented pattern, suitable for authorization decisions that depend on specific resource instances and their relationships to the requesting user + +## Risks + +- Inconsistent authorization enforcement if developers forget to add authorization checks to new controller actions + Mitigation: Implement automated code analysis rules to detect controller actions missing authorization checks, require security review for new API endpoints, use integration tests that verify authorization enforcement + Owner: Security team and API development team +- Authorization bypass vulnerabilities if NotFoundException is thrown for authorization failures, potentially enabling resource enumeration attacks + Mitigation: Establish clear guidelines for when to throw NotFoundException vs. returning 403 Forbidden, conduct security reviews of authorization error handling patterns, implement rate limiting on authorization failures + Owner: Security team +- Performance degradation from multiple authorization checks in bulk operations or complex workflows + Mitigation: Implement authorization result caching where appropriate, batch authorization checks for bulk operations, monitor authorization service performance metrics + Owner: Engineering team and performance engineering + +## Implementation Notes + +- Inject IAuthorizationService in controller constructors and store as private readonly field: private readonly IAuthorizationService _authorizationService; +- Call authorization service before performing protected operations: var authResult = await _authorizationService.AuthorizeAsync(User, resource, requirement); if (!authResult.Succeeded) { throw new NotFoundException(); } +- Define custom authorization requirements by implementing IAuthorizationRequirement interface and corresponding AuthorizationHandler or AuthorizationHandler classes +- Register authorization policies in Startup.cs or Program.cs using services.AddAuthorization(config => { config.AddPolicy("PolicyName", policy => { policy.RequireAssertion(...); }); }); +- For bulk operations, iterate through resources and verify authorization for each: foreach (var collection in collections) { if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyUserAccess)).Succeeded) { throw new NotFoundException(); } } + +## Continuation Context + + +Verify commands: +- grep -r 'IAuthorizationService' --include='*Controller.cs' src/ | wc -l +- grep -r 'AuthorizeAsync' --include='*Controller.cs' src/ | grep -v '//' | wc -l +- grep -r '\[Authorize' --include='*Controller.cs' src/ | wc -l + +Accept when: +- All protected controller actions contain at least one IAuthorizationService.AuthorizeAsync() call before performing operations on protected resources +- Authorization policies are configured using services.AddAuthorization() and custom requirements implement IAuthorizationRequirement +- Authorization failures result in appropriate HTTP error responses (NotFoundException, UnauthorizedAccessException, or BadRequestException with error messages) + +## Enforcement + +- Verified by: Static code analysis tools scanning for controller actions with [Authorize] attributes missing corresponding AuthorizeAsync calls +- Verified by: Integration tests verifying authorization enforcement for each protected endpoint with unauthorized users +- Verified by: Security-focused code reviews checking authorization logic in new and modified controller actions +- Verified by: Automated grep-based verification commands in CI pipeline checking for presence of IAuthorizationService usage patterns +- Violation handling: CI pipeline fails if static analysis detects controller actions missing required authorization checks +- Violation handling: Pull requests with new API endpoints require security team approval before merging +- Violation handling: Security incidents involving authorization bypass trigger immediate remediation and retrospective analysis +- Violation handling: Quarterly security audits review authorization enforcement patterns across all API controllers +- Exception process: Developers must document justification for any controller action that does not follow standard authorization patterns +- Exception process: Security team reviews and approves exceptions through pull request comments or security review tickets +- Exception process: Approved exceptions are documented in code comments with reference to exception ID and approval date +- Exception process: Exceptions are reviewed annually to determine if they can be brought into compliance with standard patterns \ No newline at end of file diff --git a/docs/adr/fdb27347-e3f0-49f2-a5db-da80b3eab9d3-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-factories-configure.md b/docs/adr/fdb27347-e3f0-49f2-a5db-da80b3eab9d3-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-factories-configure.md new file mode 100644 index 000000000000..e0c1c0ea4e8b --- /dev/null +++ b/docs/adr/fdb27347-e3f0-49f2-a5db-da80b3eab9d3-adopt-savechanges-pattern-for-database-persistence-in-scim-integration-tests-test-factories-configure.md @@ -0,0 +1,113 @@ +# Adopt SaveChanges Pattern for Database Persistence in SCIM Integration Tests: Test Factories Configure + +Status: proposed +Date: 2024-01-09 +Deciders: Detection Pipeline (automated) + +## Context + +- Integration tests for SCIM endpoints require database state management to validate API behavior against persisted data +- The test infrastructure uses a DatabaseContext with explicit SaveChanges calls to commit test data setup and verify state transitions +- Test authentication is implemented via custom AuthenticationHandler with claims-based identity for simulating organizational access +- The ScimApplicationFactory configures a test server with ASP.NET Core authentication and authorization middleware for integration testing +- Async HTTP operations (GetAsync, PostAsync, PutAsync, PatchAsync) against SCIM v2 endpoints require coordinated database persistence + +## Problem Statement + +Integration tests for SCIM API endpoints need a consistent pattern for managing database state across test setup, execution, and verification phases. Without explicit control over when changes are persisted, tests may encounter race conditions, incomplete state, or unpredictable behavior when validating API responses against database state. + +## Decision + +1. MUST: Test factories MUST configure authentication using AuthenticationHandler with ClaimsIdentity for organizational context + +## Policy Block + +- MUST Test factories MUST configure authentication using AuthenticationHandler with ClaimsIdentity for organizational context + +In scope: +- SCIM integration tests in bitwarden_license/test/Scim.IntegrationTest +- ScimApplicationFactory test infrastructure +- DatabaseContext operations within integration test scope +- HTTP endpoint tests for /v2/{organizationId}/groups and /v2/{organizationId}/users + +Out of scope: +- Unit tests that mock database access +- Production application code outside test scope +- End-to-end tests using real external services +- Performance or load testing scenarios + +## Rationale + +- Explicit SaveChanges calls provide deterministic control over when test data is committed, ensuring consistent state for API validation +- The pattern is evidenced by DatabaseContext.SaveChanges() usage in ScimApplicationFactory.cs with 79.60% confidence across integration test infrastructure +- Async HTTP operations require coordinated persistence to avoid race conditions between database writes and API reads +- Claims-based authentication in tests mirrors production authorization patterns while maintaining test isolation + +## Consequences + +Positive: +- Deterministic test execution with explicit control over database state transitions +- Clear separation between test setup (data creation) and test execution (API calls) +- Reduced flakiness from race conditions between database writes and HTTP requests +- Test infrastructure mirrors production authentication and authorization patterns + +Negative: +- Requires manual SaveChanges management, increasing test code verbosity +- Risk of forgotten SaveChanges calls leading to test failures or false negatives +- Tighter coupling between test code and Entity Framework persistence semantics +- Additional cognitive load for test authors to manage transaction boundaries + +## Alternatives + +- Use auto-commit or implicit SaveChanges via repository pattern (rejected) + Rejected because: Implicit commits reduce test determinism and make it harder to control exact timing of persistence relative to HTTP operations + When valid: Valid for unit tests with mocked repositories where persistence timing is not critical +- Use in-memory database without explicit SaveChanges (rejected) + Rejected because: In-memory databases may not enforce same constraints as production databases, reducing test fidelity + When valid: Valid for fast unit tests where database constraint validation is not required +- Use transaction rollback pattern with automatic cleanup (deferred) + When valid: Valid for future optimization to improve test isolation and cleanup, but requires infrastructure changes + +## Risks + +- Forgotten SaveChanges calls cause intermittent test failures that are difficult to diagnose + Mitigation: Establish code review checklist for integration tests; consider static analysis to detect DatabaseContext usage without SaveChanges + Owner: QA and Test Infrastructure Team +- Test database state leakage between tests if SaveChanges is called without proper cleanup + Mitigation: Implement test isolation via transaction rollback or database reset between test runs + Owner: Test Infrastructure Team +- Performance degradation if SaveChanges is called too frequently in test setup + Mitigation: Batch related entity creation and call SaveChanges once per logical setup phase + Owner: Engineering Team + +## Implementation Notes + +- Call DatabaseContext.SaveChanges() after all test entities are created but before executing HTTP requests +- Use async/await consistently for both SaveChangesAsync() and HTTP client methods to maintain proper execution order +- Configure TestAuthHandler with appropriate claims (e.g., orgadmin) to match the organizational context of test data +- Inject NoopMailService and other test doubles in ScimApplicationFactory to prevent external side effects during integration tests + +## Continuation Context + + +Verify commands: +- grep -r 'DatabaseContext\.SaveChanges' bitwarden_license/test/Scim.IntegrationTest/ +- grep -r 'await.*\(GetAsync\|PostAsync\|PutAsync\|PatchAsync\)' bitwarden_license/test/Scim.IntegrationTest/ | wc -l +- grep -r 'AddAuthentication.*Test' bitwarden_license/test/Scim.IntegrationTest/Factories/ + +Accept when: +- All integration tests in Scim.IntegrationTest call SaveChanges before HTTP operations +- Test authentication is configured via AuthenticationHandler with claims-based identity +- Async HTTP methods are used consistently with await for database coordination + +## Enforcement + +- Verified by: Code review of integration test pull requests +- Verified by: Static analysis to detect DatabaseContext usage patterns +- Verified by: CI pipeline test execution monitoring for flaky tests +- Violation handling: Pull request comments requesting explicit SaveChanges calls +- Violation handling: Test failure investigation to identify missing persistence calls +- Violation handling: Refactoring guidance provided during code review +- Exception process: Document rationale in test comments if alternative persistence pattern is required +- Exception process: Obtain approval from test infrastructure team lead +- Exception process: Add test-specific documentation explaining deviation from standard pattern \ No newline at end of file diff --git a/docs/adr/ffddbcb9-7c00-4a51-a626-c52702ef8e99-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-redis-connection-failures.md b/docs/adr/ffddbcb9-7c00-4a51-a626-c52702ef8e99-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-redis-connection-failures.md new file mode 100644 index 000000000000..32feadea4392 --- /dev/null +++ b/docs/adr/ffddbcb9-7c00-4a51-a626-c52702ef8e99-adopt-stackexchange-redis-with-extended-caching-infrastructure-for-distributed-cache-redis-connection-failures.md @@ -0,0 +1,113 @@ +# Adopt StackExchange.Redis with Extended Caching Infrastructure for Distributed Cache: Redis Connection Failures + +Status: proposed +Date: 2024-01-15 +Deciders: Detection Pipeline (automated) + +## Context + +- The system requires distributed caching capabilities to support scalable, multi-instance deployments where cache state must be shared across application nodes +- Redis was selected as the backing store for distributed caching, requiring integration through Microsoft.Extensions.Caching.StackExchangeRedis +- The Core utilities layer provides extended cache service registration that wraps the standard IDistributedCache interface with connection management and error handling +- Cache connection failures must be handled gracefully with logging to prevent application startup failures when Redis is temporarily unavailable + +## Problem Statement + +Applications requiring distributed caching need a standardized approach to configure Redis-backed cache instances with proper connection management, error handling, and integration with the dependency injection container, while maintaining compatibility with the Microsoft.Extensions.Caching.Distributed abstractions. + +## Decision + +1. MUST: Redis connection failures during cache initialization MUST be logged with LogError including the cache name and exception details + +## Policy Block + +- MUST Redis connection failures during cache initialization MUST be logged with LogError including the cache name and exception details + +In scope: +- All distributed cache implementations within the Bit.Core namespace +- Service registration code in ExtendedCacheServiceCollectionExtensions +- Redis connection management and error handling for cache instances +- Cache configuration sourced from Bit.Core.Settings + +Out of scope: +- In-memory caching implementations (IMemoryCache) +- Application-specific cache key naming conventions +- Cache expiration policies and TTL configuration +- Redis cluster configuration and topology decisions + +## Rationale + +- StackExchange.Redis is the de facto standard Redis client for .NET, providing robust connection multiplexing and async support that aligns with Microsoft's distributed caching abstractions +- Centralizing cache registration in ExtendedCacheServiceCollectionExtensions ensures consistent error handling and connection management across all cache instances +- Explicit error logging for Redis connection failures enables operational visibility while preventing application startup failures when cache infrastructure is temporarily unavailable +- The pattern detected in src/Core/Utilities/ExtendedCacheServiceCollectionExtensions.cs demonstrates established usage with proper dependency injection integration + +## Consequences + +Positive: +- Standardized distributed caching infrastructure reduces implementation variance across services +- Graceful degradation through error handling prevents cache unavailability from blocking application startup +- Integration with Microsoft.Extensions.Caching.Distributed enables compatibility with ASP.NET Core middleware and third-party libraries +- Connection multiplexing through StackExchange.Redis improves resource utilization and connection pool management + +Negative: +- Tight coupling to StackExchange.Redis makes migration to alternative Redis clients or cache providers more difficult +- Additional abstraction layer in ExtendedCacheServiceCollectionExtensions adds complexity compared to direct RedisCacheOptions configuration +- Error handling that allows startup despite Redis failures may mask configuration issues until runtime cache operations fail +- Dependency on Bit.Core.Settings and Bit.Core.Utilities creates coupling between cache infrastructure and core framework components + +## Alternatives + +- Use Microsoft.Extensions.Caching.Memory (IMemoryCache) for all caching needs (rejected) + Rejected because: In-memory caching does not support distributed scenarios where cache state must be shared across multiple application instances or nodes + When valid: Single-instance deployments or scenarios where cache locality is acceptable +- Directly configure RedisCacheOptions in each consuming service without ExtendedCacheServiceCollectionExtensions (rejected) + Rejected because: Direct configuration duplicates connection management and error handling logic across services, reducing consistency and maintainability + When valid: Services with unique Redis connection requirements that cannot be standardized +- Use alternative distributed cache providers such as NCache, Memcached, or SQL Server distributed cache (rejected) + Rejected because: Redis provides superior performance characteristics and feature set for distributed caching, and StackExchange.Redis is already integrated into the core infrastructure + When valid: Environments with existing investment in alternative cache infrastructure or specific compliance requirements + +## Risks + +- Redis infrastructure outages cause cache operations to fail at runtime despite successful application startup + Mitigation: Implement circuit breaker patterns around cache operations and ensure application logic degrades gracefully when cache is unavailable + Owner: engineering team +- Connection string configuration errors in Bit.Core.Settings may not be detected until cache operations are attempted + Mitigation: Add health check endpoints that verify Redis connectivity and include cache health in application readiness probes + Owner: engineering team +- Version incompatibilities between Microsoft.Extensions.Caching.StackExchangeRedis and StackExchange.Redis may introduce breaking changes + Mitigation: Pin dependency versions in package management and test cache functionality in CI pipeline before upgrading + Owner: engineering team + +## Implementation Notes + +- Register distributed cache services by calling AddExtendedCache on IServiceCollection during application startup configuration +- Configure Redis connection strings in Bit.Core.Settings with appropriate timeout and retry settings for the deployment environment +- Ensure logging infrastructure is configured before cache registration to capture connection failure diagnostics +- Consider implementing IHealthCheck for Redis connectivity to expose cache health through monitoring endpoints + +## Continuation Context + + +Verify commands: +- grep -r 'Microsoft.Extensions.Caching.StackExchangeRedis' --include='*.csproj' . +- grep -r 'AddExtendedCache' --include='*.cs' . | grep -v 'ExtendedCacheServiceCollectionExtensions.cs' +- grep -r 'ConnectionMultiplexer.Connect' --include='*.cs' . + +Accept when: +- All distributed cache registrations use AddExtendedCache from Bit.Core.Utilities +- Microsoft.Extensions.Caching.StackExchangeRedis package reference exists in Core project dependencies +- Redis connection failures are logged with LogError including cache name and exception details + +## Enforcement + +- Verified by: Code review verification that cache registration uses ExtendedCacheServiceCollectionExtensions +- Verified by: Static analysis to detect direct RedisCacheOptions configuration outside approved extension methods +- Verified by: Dependency scanning to verify StackExchange.Redis is used through Microsoft.Extensions.Caching.StackExchangeRedis +- Violation handling: Pull requests introducing direct Redis configuration without ExtendedCacheServiceCollectionExtensions require architectural review +- Violation handling: Alternative cache providers require ADR documentation justifying deviation from standard +- Violation handling: Missing error handling for Redis connection failures blocks merge until logging is added +- Exception process: Submit exception request documenting specific technical constraints preventing use of ExtendedCacheServiceCollectionExtensions +- Exception process: Architectural review board evaluates whether constraints justify deviation or whether extension method should be enhanced +- Exception process: Approved exceptions must document alternative error handling and connection management approach \ No newline at end of file diff --git a/docs/adr/fffb6c6b-569b-4502-bfd8-77134aa02e25-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md b/docs/adr/fffb6c6b-569b-4502-bfd8-77134aa02e25-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md new file mode 100644 index 000000000000..acfb1fc04488 --- /dev/null +++ b/docs/adr/fffb6c6b-569b-4502-bfd8-77134aa02e25-use-embedded-fake-rsa-keys-for-testing-cryptographic-operations-fake-rsa-key.md @@ -0,0 +1,125 @@ +# Use Embedded Fake RSA Keys for Testing Cryptographic Operations: Fake Rsa Key + +Status: proposed +Date: 2025-01-17 +Deciders: Detection Pipeline (automated) + +## Activation + +This ADR is always active for all test code requiring cryptographic key fixtures. + +## Context + +- The Rust SDK requires testing of cryptographic operations including RSA key generation, cipher operations, and key management without depending on external key files or runtime key generation +- Test execution must be deterministic and repeatable across environments without network access or filesystem dependencies for key material +- The codebase uses bitwarden_crypto::SymmetricCryptoKey and RSA_POOL for cryptographic operations that require valid key material during testing +- Multiple test scenarios require distinct RSA key pairs to validate key isolation, organization key management, and user key generation workflows +- The rsa_keys module provides a dedicated location for test fixtures, separating test data from production cryptographic key management + +## Problem Statement + +Testing cryptographic operations requires valid RSA key material, but generating keys at runtime introduces non-determinism, performance overhead, and potential test flakiness. External key files create filesystem dependencies and complicate test environment setup. The system needs a reliable, fast, and isolated approach to provide cryptographic test fixtures. + +## Decision + +1. SHOULD: Fake RSA key constants SHOULD be organized in a dedicated module (e.g., rsa_keys.rs) separate from production cryptographic code + +## Policy Block + +- SHOULD Fake RSA key constants SHOULD be organized in a dedicated module (e.g., rsa_keys.rs) separate from production cryptographic code + +In scope: +- All test modules in util/RustSdk/rust/src/ requiring RSA key material +- Unit tests for cipher operations, key generation, and cryptographic workflows +- Integration tests validating FFI boundaries with C-compatible string types +- Test fixtures for user key generation (generate_user_keys) and organization key generation (generate_organization_keys) + +Out of scope: +- Production cryptographic key generation and management +- Runtime key derivation from user passwords or master keys +- Key storage and persistence mechanisms +- External key management systems or hardware security modules + +Exceptions: +- EXC-001: Performance benchmarks require measuring actual key generation overhead +- EXC-002: Security tests specifically validate key generation randomness or entropy + +## Rationale + +- Embedded fake RSA keys eliminate runtime key generation overhead, reducing test execution time from seconds to milliseconds per test case +- String constants provide deterministic test fixtures that produce identical results across all environments, eliminating flakiness from cryptographic randomness +- The pattern observed in util/RustSdk/rust/src/rsa_keys.rs demonstrates a working implementation with 5 distinct fake keys supporting multiple test scenarios +- Separating test fixtures into a dedicated module maintains clear boundaries between test infrastructure and production cryptographic code, reducing risk of test key leakage + +## Consequences + +Positive: +- Test execution speed improves dramatically by eliminating expensive RSA key generation operations +- Test determinism increases as identical key material produces consistent cryptographic outputs across test runs +- Test environment setup simplifies by removing filesystem dependencies and external key file management +- Test isolation improves as each test can use distinct numbered key fixtures without state sharing + +Negative: +- Embedded PEM strings increase source code size and reduce readability in test modules +- Fake keys do not validate actual key generation logic, requiring separate tests for key generation workflows +- Risk of accidental production use if fake keys are not properly scoped to test-only modules +- Key rotation or cryptographic algorithm updates require manual regeneration of all fake key constants + +## Alternatives + +- Generate RSA keys at runtime during test setup using cryptographic libraries (rejected) + Rejected because: Runtime key generation introduces 100-500ms overhead per test and non-deterministic output that complicates assertion validation + When valid: Only for security tests explicitly validating key generation randomness or entropy properties +- Load RSA keys from external PEM files in test fixtures directory (rejected) + Rejected because: Filesystem dependencies complicate test environment setup and introduce failure modes from missing files or incorrect paths + When valid: When testing actual file I/O operations or validating key import from external sources +- Use a single shared fake RSA key for all tests (rejected) + Rejected because: Single key prevents testing key isolation scenarios and creates potential test coupling through shared state + When valid: For simple unit tests that only require valid key material without testing key-specific behavior + +## Risks + +- Fake RSA keys accidentally used in production code paths, exposing known private keys + Mitigation: Use conditional compilation (#[cfg(test)]) to ensure fake keys are only compiled in test builds. Implement code review checks for any use of _FAKE_RSA_KEY_ constants outside test modules. + Owner: Security team and code reviewers +- Fake keys become outdated as cryptographic standards evolve (e.g., minimum key size increases) + Mitigation: Document key generation parameters in comments. Include verification tests that validate key properties (size, format). Schedule periodic review of fake key fixtures during security audits. + Owner: Security team +- Over-reliance on fake keys masks bugs in actual key generation logic + Mitigation: Maintain separate test suite that validates actual key generation functions. Use fake keys only for testing operations that consume keys, not for testing key generation itself. + Owner: Engineering team + +## Implementation Notes + +- Create a dedicated rsa_keys.rs module with #[cfg(test)] annotation to ensure test-only compilation +- Define fake key constants with descriptive names: const _FAKE_RSA_KEY_0: &str = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"; +- Generate fake keys once using openssl genrsa -out key.pem 2048 && openssl pkcs8 -topk8 -nocrypt -in key.pem, then embed the output as string literals +- Document the key generation parameters (algorithm, key size, format) in module-level comments for future maintenance +- Use numbered sequences (_FAKE_RSA_KEY_0 through _FAKE_RSA_KEY_4) to support tests requiring multiple distinct keys +- Import fake keys in test modules using use crate::rsa_keys::_FAKE_RSA_KEY_0; to maintain clear dependency tracking + +## Continuation Context + + +Verify commands: +- grep -r '_FAKE_RSA_KEY_' --include='*.rs' --exclude-dir=target | grep -v '#\[cfg(test)\]' | grep -v 'mod tests' | grep -v '/tests/' || echo 'No production usage found' +- grep -r 'BEGIN PRIVATE KEY' --include='*.rs' util/RustSdk/rust/src/rsa_keys.rs | wc -l +- cargo test --package rust-sdk --lib rsa_keys -- --nocapture 2>&1 | grep -i 'test result' || echo 'Tests executed' + +Accept when: +- All fake RSA key constants are defined in test-only modules with #[cfg(test)] or within mod tests blocks +- At least 5 distinct fake RSA key constants are available in util/RustSdk/rust/src/rsa_keys.rs with sequential numbering +- No references to _FAKE_RSA_KEY_ constants appear in production code paths outside test modules +- All fake key constants contain valid PEM-encoded private key blocks that can be parsed by cryptographic libraries + +## Enforcement + +- Verified by: Automated grep checks in CI pipeline scanning for _FAKE_RSA_KEY_ usage outside test modules +- Verified by: Code review checklist item verifying test fixtures are properly scoped with #[cfg(test)] +- Verified by: Static analysis rules flagging use of test-only constants in production code paths +- Violation handling: CI build fails if fake key constants are referenced outside test-scoped modules +- Violation handling: Code review blocks merge if test fixtures lack proper conditional compilation guards +- Violation handling: Security scan alerts trigger immediate review if known test keys appear in production artifacts +- Exception process: Submit exception request to test lead with documented rationale for non-standard key fixture usage +- Exception process: Security team review required for any exception involving cryptographic test patterns +- Exception process: Document approved exceptions in ADR amendments with expiration date and review schedule \ No newline at end of file