-
Notifications
You must be signed in to change notification settings - Fork 138
[review] Security Guide #2321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[review] Security Guide #2321
Changes from all commits
0440376
af9c5d8
b4aa6e8
83ce6d5
f11482f
7973567
abcf040
44a9aa4
68a8382
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,15 +39,15 @@ As access control relies on verified claims, authentication is a mandatory prere | |
| According to key concept [Pluggable Building Blocks](./overview#key-concept-pluggable), the authentication method can be configured freely. | ||
| CAP [leverages platform services](overview#key-concept-platform-services) to provide proper authentication strategies to cover all relevant scenarios: | ||
|
|
||
| - For _local development_ and _unit testing_, [Mock User Authentication](#mock-user-auth) is an appropriate built-in authentication feature. | ||
| - For _local development_ and _unit testing_, [Mock User Authentication](#mock-user-authentication) is an appropriate built-in authentication feature. | ||
|
|
||
| - For _cloud deployments_, in particular deployments for production, CAP provides integration of several identity services out of the box: | ||
| - [Identity Authentication Service (IAS)](#ias-auth) provides a full-fledged [OpenId Connect](https://openid.net/connect/) compliant, cross-landscape identity management as first choice for applications. | ||
| - [XS User Authentication and Authorization Service (XSUAA)](https://help.sap.com/docs/CP_AUTHORIZ_TRUST_MNG) is an [OAuth 2.0](https://oauth.net/2/)-based authorization server to support existing applications and services in the scope of individual BTP landscapes. | ||
| - CAP applications can run IAS and XSUAA in [hybrid mode](#hybrid-auth) to support a smooth migration from XSUAA to IAS. | ||
|
|
||
|
|
||
| ## Mock User Authentication { #mock-user-auth } | ||
| ## Mock User Authentication | ||
|
|
||
| In non-production profile, by default, CAP creates a security configuration which accepts _mock users_. | ||
| As this authentication strategy is a built-in feature which does not require any platform service, it is perfect for **unit testing and local development scenarios**. | ||
|
|
@@ -140,9 +140,9 @@ curl http://localhost:4004/odata/v4/admin/Books --verbose | |
| results in a `401` error response from the server indicating that the anonymous user has been rejected due to missing authentication. | ||
| This is true for all endpoints including the web application page at `/index.html`. | ||
|
|
||
| Mock users require **basic authentication**, hence sending the same request on behalf of mock user `alice` (password: `basic`) with | ||
| Mock users require **basic authentication**, hence sending the same request on behalf of mock user `alice` (no password) with | ||
| ```sh | ||
| curl http://alice:basic@localhost:4004/odata/v4/admin/Books | ||
| curl http://alice:@localhost:4004/odata/v4/admin/Books | ||
| ``` | ||
| returns successfully (HTTP response `200`). | ||
|
|
||
|
|
@@ -309,7 +309,7 @@ Integration tests running in production profile should verify that unauthenticat | |
| - cross-landscape user propagation (including on-premise) | ||
| - streamlined SAP and non-SAP system [integration](https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/integrating-service) (due to [OpenId Connect](https://openid.net/connect/) compliance) | ||
|
|
||
| IAS authentication is best configured and tested in the Cloud, so let's enhance the started bookshop sample application with a deployment descriptor for SAP BTP, Cloud Foundry Runtime (CF). | ||
| IAS authentication is best configured and tested in the Cloud, so let's enhance the [previously started bookshop sample application](#mock-user-authentication) with a deployment descriptor for SAP BTP, Cloud Foundry Runtime (CF). | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It feels kind of hidden that we started an example. WDYT about making "Set up a Sample" an own section so that it can be found easily? |
||
|
|
||
|
|
||
| ### Get Ready with IAS { #ias-ready } | ||
|
|
@@ -324,7 +324,7 @@ towards your IAS tenant to use it as identity provider for applications in your | |
| - Ensure your development environment is [prepared for deploying](../deploy/to-cf#prerequisites) on CF, | ||
| in particular you require a `cf` CLI session targeting a CF space in the test subaccount (test with `cf target`). | ||
|
|
||
| You can continue with the sample [already created](#mock-user-auth). In the project root folder, execute | ||
| You can continue with the sample [already created](#mock-user-authentication). In the project root folder, execute | ||
|
|
||
| ```sh | ||
| cds add mta | ||
|
|
@@ -417,6 +417,7 @@ and wait until the application is up and running. | |
| You can test the status with `cf apps` on CLI level or in BTP Cockpit, alternatively. | ||
|
|
||
| The startup log should confirm the activated IAS authentication: | ||
|
|
||
| <div class="java"> | ||
|
|
||
| ```sh | ||
|
|
@@ -426,7 +427,11 @@ The startup log should confirm the activated IAS authentication: | |
| </div> | ||
|
|
||
| <div class="node"> | ||
|
|
||
| ```sh | ||
| TODO | ||
| ``` | ||
|
Comment on lines
+431
to
+433
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs to be filled |
||
|
|
||
| </div> | ||
|
|
||
| ::: tip | ||
|
|
@@ -677,14 +682,15 @@ The same is true for the logout flow. | |
| ::: | ||
|
|
||
|
|
||
| Now re-deploy the solution by running | ||
| Now re-deploy the solution: | ||
|
|
||
| ```sh | ||
| cds up | ||
| ``` | ||
|
|
||
| and test the application via URL provided in the Cockpit. | ||
| The Application Router should redirect to a login flow where you can enter the credentials of a [test user](#ias-admin) created before. | ||
| Test the application using the URL provided in the Cockpit. | ||
|
|
||
| The Application Router should redirect to a login flow where you can enter the credentials of a [test user](#ias-admin) you created before in the Administration Console for IAS. | ||
|
|
||
|
|
||
| ## XSUAA Authentication { #xsuaa-auth } | ||
|
|
@@ -706,34 +712,32 @@ XSUAA authentication is best configured and tested in the Cloud, so let's enhanc | |
| Before working with XSUAA on CF, you need to ensure your development environment is [prepared for deploying](../deploy/to-cf#prerequisites) to CF. | ||
| In particular, you require a `cf` CLI session targeting a CF space in the test subaccount (test with `cf target`). | ||
|
|
||
| You can continue with the bookshop sample create for the [mock users](#mock-user-auth) or, alternatively, you can also enhance the [IAS-based](#ias-auth) application. | ||
| :::details If you haven't prepared a sample yet... | ||
|
|
||
| If there is no deployment descriptor yet, execute in the project root folder | ||
| You can create a bookshop sample as described in [Mock User Authentication](#mock-user-authentication). | ||
|
|
||
| Execute the following two commands in the project root folder, only if you haven't prepared your sample for IAS in the previous section already. | ||
|
|
||
| To make your application ready for deployment to CF: | ||
|
|
||
| ```sh | ||
| cds add mta | ||
| ``` | ||
|
|
||
| <div class="impl java"> | ||
|
|
||
| ::: tip | ||
| Command `add mta` will enhance the project with `cds-starter-cloudfoundry` and therefore all [dependencies required for security](../../java/security#maven-dependencies) are added transitively. | ||
| ::: | ||
|
|
||
| </div> | ||
|
|
||
| to make your application ready for deployment to CF. | ||
|
|
||
| You also need to configure DB support: | ||
|
|
||
| ```sh [SAP HANA] | ||
| cds add hana | ||
| ``` | ||
|
|
||
| ::: tip For Java | ||
| Command `add mta` will enhance the project with `cds-starter-cloudfoundry` and therefore all [dependencies required for security](../../java/security#maven-dependencies) are added transitively. | ||
|
|
||
| ::: | ||
|
|
||
| ### Adding XSUAA { #adding-xsuaa } | ||
|
|
||
| Now the application is ready for enhancing with XSUAA-support: | ||
| Enhance your [sample application](#mock-user-authentication) with XSUAA-support: | ||
|
|
||
| <div class="impl java"> | ||
|
|
||
|
|
@@ -1278,7 +1282,7 @@ With `cds.security.authentication.authenticateMetadataEndpoints: false` you can | |
|
|
||
| <div class="node"> | ||
|
|
||
| Automatic authentication enforcement can be disabled via feature flag <Config>cds.requires.auth.restrict_all_services: false</Config>, or by using [mocked authentication](#mock-user-auth) explicitly in production. | ||
| Automatic authentication enforcement can be disabled via feature flag <Config>cds.requires.auth.restrict_all_services: false</Config>, or by using [mocked authentication](#mock-user-authentication) explicitly in production. | ||
|
|
||
| </div> | ||
|
|
||
|
|
@@ -1337,7 +1341,9 @@ In such architectures, CAP authentication is obsolete and can be deactivated ent | |
| </div> | ||
|
|
||
| <div class="node"> | ||
|
|
||
| TODO | ||
|
|
||
|
Comment on lines
+1344
to
+1346
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs to be filled |
||
| </div> | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -105,12 +105,12 @@ context db { | |||||
| ... | ||||||
| } | ||||||
|
|
||||||
| entity Issues : cuid { // implicitly auto-exposed (by composition) | ||||||
| entity Issues : cuid { // implicitly auto-exposed (by composition in Components) | ||||||
| category: Association to Categories; | ||||||
| ... | ||||||
| } | ||||||
|
|
||||||
| entity Components : cuid { // explicitly exposed (by projection) | ||||||
| entity Components : cuid { // explicitly exposed (by projection in IssuesService) | ||||||
| issues: Composition of many Issues; | ||||||
| ... | ||||||
| } | ||||||
|
|
@@ -262,21 +262,35 @@ Restrictions can be defined on different types of CDS resources, but there are s | |||||
| | entity | <Y/> | <Y/> | <Y/><sup>1</sup> | | | ||||||
| | action/function | <Na/> | <Y/> | <Na/><sup>2</sup> | = `@requires` | | ||||||
|
|
||||||
| > <sup>1</sup>For bound actions and functions that are not bound against a collection, Node.js supports instance-based authorization at the entity level. For example, you can use `where` clauses that *contain references to the model*, such as `where: CreatedBy = $user`. For all bound actions and functions, Node.js supports simple static expressions at the entity level that *don't have any reference to the model*, such as `where: $user.level = 2`. | ||||||
| > <sup>1</sup>For bound actions and functions that are not bound against a collection, Node.js supports instance-based authorization at the entity level, see [link] (somewhere in Node.js docs)<br> | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I felt that there was too much text that could be part of the runtime docs. I'm not saying is has to but maybe we can find a place for that and set a link here. Would be preferred. |
||||||
| > <sup>2</sup> For unbound actions and functions, Node.js supports simple static expressions that *don't have any reference to the model*, such as `where: $user.level = 2`. | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it say "bound and unbound actions and functions"? In consequence we should add
Suggested change
|
||||||
|
|
||||||
| Unsupported privilege properties are ignored by the runtime. Especially, for bound or unbound actions, the `grant` property is implicitly removed (assuming `grant: '*'` instead). The same also holds for functions: | ||||||
|
|
||||||
| ```cds | ||||||
| ::: code-group | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel it does make sense to show a wrong version and the resulting model after implicitly removing it. WDYT? |
||||||
| ```cds [Model w/ unsupported privilege properties] | ||||||
| service CatalogService { | ||||||
| entity Products as projection on db.Products { ... } | ||||||
| actions { | ||||||
| @(requires: 'Admin') | ||||||
| action addRating (stars: Integer); | ||||||
| } | ||||||
| function getViewsCount @(restrict: [{ to: 'Admin' }]) () returns Integer; | ||||||
| function getViewsCount @(restrict: [{ grant: 'READ' to: 'Admin' }]) () returns Integer; | ||||||
| } | ||||||
| ``` | ||||||
| ```cds [Resulting model] | ||||||
| service CatalogService { | ||||||
| entity Products as projection on db.Products { ... } | ||||||
| actions { | ||||||
| @(requires: 'Admin') // is already in implicit {grant: '*'} | ||||||
| action addRating (stars: Integer); | ||||||
| } | ||||||
| //unsupported property is removed, means implicit { grant: '*'} | ||||||
| function getViewsCount @(restrict: [{ to: 'Admin' }]) () returns Integer; | ||||||
| } | ||||||
|
|
||||||
| ``` | ||||||
| ::: | ||||||
|
|
||||||
|
|
||||||
| ### Combined Restrictions { #combined-restrictions} | ||||||
|
|
@@ -413,7 +427,25 @@ The [restrict annotation](#restrict-annotation) for an entity allows you to enfo | |||||
| In addition, you can define a `where`-condition that further limits the set of accessible instances. | ||||||
| This condition, which acts like a filter, establishes *instance-based authorization*. | ||||||
|
|
||||||
| ### Filter Conditions { #filter-consitions } | ||||||
| ### Filter Conditions | ||||||
|
|
||||||
| For instance, a user is allowed to read or edit `Orders` (defined with the `managed` aspect) that they have created: | ||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This idea was to move the example first, as we often do it in capire. We could do the same in other sections as well, if we agree on doing so. This is just an example to show what I mean. |
||||||
|
|
||||||
| ```cds | ||||||
| annotate Orders with @(restrict: [ | ||||||
| { grant: ['READ', 'UPDATE', 'DELETE'], where: (CreatedBy = $user) } ]); | ||||||
| ``` | ||||||
|
|
||||||
| Or a `Vendor` can only edit articles on stock (that means `Articles.stock` positive): | ||||||
|
|
||||||
| ```cds | ||||||
| annotate Articles with @(restrict: [ | ||||||
| { grant: ['UPDATE'], to: 'Vendor', where: (stock > 0) } ]); | ||||||
| ``` | ||||||
|
|
||||||
| ::: tip | ||||||
| Filter conditions declared as **compiler expressions** ensure validity at compile time and therefore strengthen security. | ||||||
| ::: | ||||||
|
|
||||||
| The condition defined in the `where` clause typically associates domain data with static [user claims](cap-users#claims). | ||||||
| Basically, it *either filters the result set in queries or accepts only write operations on instances that meet the condition*. | ||||||
|
|
@@ -444,24 +476,6 @@ You can define filter conditions in the `where`-clause of restrictions based on | |||||
| </div> | ||||||
|
|
||||||
|
|
||||||
| For instance, a user is allowed to read or edit `Orders` (defined with the `managed` aspect) that they have created: | ||||||
|
|
||||||
| ```cds | ||||||
| annotate Orders with @(restrict: [ | ||||||
| { grant: ['READ', 'UPDATE', 'DELETE'], where: (CreatedBy = $user) } ]); | ||||||
| ``` | ||||||
|
|
||||||
| Or a `Vendor` can only edit articles on stock (that means `Articles.stock` positive): | ||||||
|
|
||||||
| ```cds | ||||||
| annotate Articles with @(restrict: [ | ||||||
| { grant: ['UPDATE'], to: 'Vendor', where: (stock > 0) } ]); | ||||||
| ``` | ||||||
|
|
||||||
| ::: tip | ||||||
| Filter conditions declared as **compiler expressions** ensure validity at compile time and therefore strengthen security. | ||||||
| ::: | ||||||
|
|
||||||
| At runtime you'll find filter predicates attached to the appropriate CQN queries matching the instance-based condition. | ||||||
|
|
||||||
| :::warning Modification of Statements | ||||||
|
|
||||||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PDT42 Is this correct or does Alice have a password? Please also check the curl command for correctness. Thanks :)