diff --git a/java/assets/java-ias.excalidraw b/java/assets/java-ias.excalidraw new file mode 100644 index 000000000..4eb5cf76a --- /dev/null +++ b/java/assets/java-ias.excalidraw @@ -0,0 +1,1470 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "rectangle", + "version": 307, + "versionNonce": 1913304530, + "index": "b1V", + "isDeleted": false, + "id": "oQ3kBDHqwYLV4B8PObhgD", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1542.0909090909092, + "y": 631.7272727272725, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 229.9999999999999, + "height": 173.63636363636394, + "seed": 2066872146, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "PLL2yNJ9rgwDENQOnR1xM" + }, + { + "id": "pR3GAnjODEcOFgemlLVVM", + "type": "arrow" + }, + { + "id": "ZXABurtWn_kb5Qh7Rwjtn", + "type": "arrow" + }, + { + "id": "B5lo9BfFX6yMA0NsYQjUg", + "type": "arrow" + }, + { + "id": "pc8sfx4zKLnHTuN1tFiax", + "type": "arrow" + }, + { + "id": "Wr8hpxyWCvjyibNXCpC1V", + "type": "arrow" + } + ], + "updated": 1718703455842, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 287, + "versionNonce": 304013390, + "index": "b1W", + "isDeleted": false, + "id": "PLL2yNJ9rgwDENQOnR1xM", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1567.9549380215733, + "y": 696.0454545454545, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 178.27194213867188, + "height": 45, + "seed": 1281047826, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703130467, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "CAP Java", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "oQ3kBDHqwYLV4B8PObhgD", + "originalText": "CAP Java", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 1953, + "versionNonce": 1285213778, + "index": "b1b", + "isDeleted": false, + "id": "pR3GAnjODEcOFgemlLVVM", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1656.5245391889525, + "y": 806.3636363636365, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 2.465543138702742, + "height": 141.89057339745568, + "seed": 1368969682, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709728010, + "link": null, + "locked": false, + "startBinding": { + "elementId": "oQ3kBDHqwYLV4B8PObhgD", + "focus": 0.017958600616737406, + "gap": 1 + }, + "endBinding": { + "elementId": "n1xEiR98l4H-fVa649moS", + "focus": 0.007042175225311119, + "gap": 1 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 2.465543138702742, + 141.89057339745568 + ] + ] + }, + { + "type": "rectangle", + "version": 445, + "versionNonce": 1504800082, + "index": "b1d", + "isDeleted": false, + "id": "2fxpAtNwd5DLZ5aaUj4jd", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1072.0000000000002, + "y": 630.4545454545446, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 229.9999999999999, + "height": 173.63636363636394, + "seed": 757597522, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "y9zabFmpll7opNdBfoJJU" + }, + { + "id": "48C5LDfRyY15oTkdsMuCc", + "type": "arrow" + }, + { + "id": "ZXABurtWn_kb5Qh7Rwjtn", + "type": "arrow" + } + ], + "updated": 1718703515525, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 437, + "versionNonce": 1467740946, + "index": "b1e", + "isDeleted": false, + "id": "y9zabFmpll7opNdBfoJJU", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1097.2880325317385, + "y": 694.7727272727266, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 179.42393493652344, + "height": 45, + "seed": 811567890, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703515525, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "AppRouter", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "2fxpAtNwd5DLZ5aaUj4jd", + "originalText": "AppRouter", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2075, + "versionNonce": 2147162770, + "index": "b1f", + "isDeleted": false, + "id": "48C5LDfRyY15oTkdsMuCc", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1303, + "y": 803.0133250666055, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 277.7402787557239, + "height": 199.35031129703088, + "seed": 1981831378, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709735507, + "link": null, + "locked": false, + "startBinding": { + "elementId": "2fxpAtNwd5DLZ5aaUj4jd", + "focus": 0.014647276922519067, + "gap": 1.0000000000001137 + }, + "endBinding": { + "elementId": "n1xEiR98l4H-fVa649moS", + "focus": -0.992988423789312, + "gap": 1 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 277.7402787557239, + 199.35031129703088 + ] + ] + }, + { + "type": "arrow", + "version": 537, + "versionNonce": 458461582, + "index": "b1j", + "isDeleted": false, + "id": "ZXABurtWn_kb5Qh7Rwjtn", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1303, + "y": 714.2808930431463, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "width": 233.54545454545496, + "height": 0.01985901891271169, + "seed": 1740174158, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709625824, + "link": null, + "locked": false, + "startBinding": { + "elementId": "2fxpAtNwd5DLZ5aaUj4jd", + "focus": -0.03457043678033462, + "gap": 1 + }, + "endBinding": { + "elementId": "oQ3kBDHqwYLV4B8PObhgD", + "focus": 0.048768301590809575, + "gap": 5.545454545453936 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 233.54545454545496, + 0.01985901891271169 + ] + ] + }, + { + "type": "text", + "version": 339, + "versionNonce": 99618638, + "index": "b1n", + "isDeleted": false, + "id": "-cwYI3NXBfuqHQ3YTiQ4h", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1383.0473258278591, + "y": 729.2272727272725, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 74.89993286132812, + "height": 25, + "seed": 1920788178, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703700871, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "forward", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "forward", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 511, + "versionNonce": 618600462, + "index": "b1o", + "isDeleted": false, + "id": "uUHrgh96QblWLRyQaIJpp", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1998.9999999999998, + "y": 918.181818181818, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 229.9999999999999, + "height": 173.63636363636394, + "seed": 923516430, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "SS50-wLLLy-PuLt_DC43f" + }, + { + "id": "B5lo9BfFX6yMA0NsYQjUg", + "type": "arrow" + }, + { + "id": "09crasjK9WuDVn4zbUChd", + "type": "arrow" + } + ], + "updated": 1718703374314, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 494, + "versionNonce": 27059790, + "index": "b1p", + "isDeleted": false, + "id": "SS50-wLLLy-PuLt_DC43f", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2024.8640289306638, + "y": 982.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 178.27194213867188, + "height": 45, + "seed": 860146766, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703374314, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "CAP Java", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "uUHrgh96QblWLRyQaIJpp", + "originalText": "CAP Java", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 532, + "versionNonce": 1886252178, + "index": "b1q", + "isDeleted": false, + "id": "yAtALBl_CP-IVF_zFp8uE", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0.5636923465960058, + "x": 1846.5500335693357, + "y": 863.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 74.89993286132812, + "height": 25, + "seed": 1098868818, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704242884, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "forward", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "forward", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 806, + "versionNonce": 231409166, + "index": "b1r", + "isDeleted": false, + "id": "B5lo9BfFX6yMA0NsYQjUg", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1773.7951053148645, + "y": 779.9139077341288, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "width": 222.38671286695308, + "height": 144.83920894813696, + "seed": 1366758418, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709625824, + "link": null, + "locked": false, + "startBinding": { + "elementId": "oQ3kBDHqwYLV4B8PObhgD", + "focus": -0.09053053925078487, + "gap": 1.704196223955364 + }, + "endBinding": { + "elementId": "uUHrgh96QblWLRyQaIJpp", + "focus": 0.021720455062198857, + "gap": 2.8181818181820972 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 222.38671286695308, + 144.83920894813696 + ] + ] + }, + { + "type": "arrow", + "version": 2155, + "versionNonce": 821680850, + "index": "b1s", + "isDeleted": false, + "id": "09crasjK9WuDVn4zbUChd", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1997.9999999999995, + "y": 999.7338039116653, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 255.0198880669659, + "height": 2.3904672944479444, + "seed": 1230738002, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709728010, + "link": null, + "locked": false, + "startBinding": { + "elementId": "uUHrgh96QblWLRyQaIJpp", + "focus": 0.07228461571905273, + "gap": 1.0000000000001137 + }, + "endBinding": { + "elementId": "n1xEiR98l4H-fVa649moS", + "focus": -0.02315918836215727, + "gap": 1 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -255.0198880669659, + 2.3904672944479444 + ] + ] + }, + { + "type": "arrow", + "version": 831, + "versionNonce": 1056279506, + "index": "b1t", + "isDeleted": false, + "id": "pc8sfx4zKLnHTuN1tFiax", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1774.4825414209952, + "y": 714.4798317734801, + "strokeColor": "#f08c00", + "backgroundColor": "#a5d8ff", + "width": 211.24473130627734, + "height": 0.8234371888067926, + "seed": 1442161298, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709746973, + "link": null, + "locked": false, + "startBinding": { + "elementId": "oQ3kBDHqwYLV4B8PObhgD", + "focus": -0.04134495091860604, + "gap": 2.3916323300862814 + }, + "endBinding": { + "elementId": "Nzm-LhJpfzcT9cPslDLwi", + "focus": -0.07077031452508135, + "gap": 8.272727272727593 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 211.24473130627734, + -0.8234371888067926 + ] + ] + }, + { + "type": "rectangle", + "version": 553, + "versionNonce": 855041934, + "index": "b1u", + "isDeleted": false, + "id": "Nzm-LhJpfzcT9cPslDLwi", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1994.0000000000002, + "y": 620.181818181818, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 229.9999999999999, + "height": 173.63636363636394, + "seed": 694358482, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "FDC8HNU5js8NyxWjqVV4e" + }, + { + "id": "pc8sfx4zKLnHTuN1tFiax", + "type": "arrow" + }, + { + "id": "7vzj14HvSTh-ZzHuyp995", + "type": "arrow" + } + ], + "updated": 1718704146222, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 558, + "versionNonce": 455785106, + "index": "b1v", + "isDeleted": false, + "id": "FDC8HNU5js8NyxWjqVV4e", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1999.6500320434573, + "y": 639.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 218.69993591308594, + "height": 135, + "seed": 2055538578, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704344507, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "(CAP Java)\nBTP Reuse \nService", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Nzm-LhJpfzcT9cPslDLwi", + "originalText": "(CAP Java) BTP Reuse Service", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 643, + "versionNonce": 1423410450, + "index": "b1w", + "isDeleted": false, + "id": "bC2ljiqjVxeq1dlCeoaRD", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1988.9999999999998, + "y": 338.181818181818, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 229.9999999999999, + "height": 173.63636363636394, + "seed": 1892294738, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "G0memCikjPpG8tHaRFaIi" + }, + { + "id": "Wr8hpxyWCvjyibNXCpC1V", + "type": "arrow" + }, + { + "id": "ad_YE9NYF8u5F7IG1nK_Y", + "type": "arrow" + } + ], + "updated": 1718704136574, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 713, + "versionNonce": 375301714, + "index": "b1x", + "isDeleted": false, + "id": "G0memCikjPpG8tHaRFaIi", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2022.136032104492, + "y": 380, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 163.72793579101562, + "height": 90, + "seed": 252069394, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704357091, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": " external\nService", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "bC2ljiqjVxeq1dlCeoaRD", + "originalText": " external\nService", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 534, + "versionNonce": 1824283726, + "index": "b1y", + "isDeleted": false, + "id": "M8S1h-iE0f7ije6a57Z_1", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 7.105427357601002e-15, + "x": 1842.5500335693357, + "y": 731.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 74.89993286132812, + "height": 25, + "seed": 1230915922, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703978403, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "forward", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "forward", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "Wr8hpxyWCvjyibNXCpC1V", + "type": "arrow", + "x": 1774, + "y": 656.0611572680664, + "width": 213.99999999999955, + "height": 170.1977375776924, + "angle": 0, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b1z", + "roundness": { + "type": 2 + }, + "seed": 1517820690, + "version": 115, + "versionNonce": 1886572366, + "isDeleted": false, + "boundElements": null, + "updated": 1718709637091, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 213.99999999999955, + -170.1977375776924 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "oQ3kBDHqwYLV4B8PObhgD", + "focus": 0.17105399747985128, + "gap": 1.9090909090911055 + }, + "endBinding": { + "elementId": "bC2ljiqjVxeq1dlCeoaRD", + "focus": 0.176090258753876, + "gap": 1.0000000000001137 + }, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "ghC2Ohyi-X1QyTIpkOpBb", + "type": "text", + "x": 1843.5435915363123, + "y": 571.9696614399338, + "width": 85.73992919921875, + "height": 25, + "angle": 5.616665672058556, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b20", + "roundness": null, + "seed": 2143317070, + "version": 127, + "versionNonce": 1570689746, + "isDeleted": false, + "boundElements": null, + "updated": 1718703709980, + "link": null, + "locked": false, + "text": "exchange", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "exchange", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "VAEcdZ4bcSyEnT1fIj64y", + "type": "text", + "x": 1383, + "y": 668, + "width": 74.03196716308594, + "height": 35, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b21", + "roundness": null, + "seed": 1448987150, + "version": 132, + "versionNonce": 1655892878, + "isDeleted": false, + "boundElements": null, + "updated": 1718703980940, + "link": null, + "locked": false, + "text": "mTLS", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "mTLS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 135, + "versionNonce": 499622542, + "index": "b22", + "isDeleted": false, + "id": "bnBwOyG7APQ_9Nxvr0kyk", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1850.984016418457, + "y": 673.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 74.03196716308594, + "height": 35, + "seed": 878046926, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703978627, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "mTLS", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "mTLS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 260, + "versionNonce": 439938322, + "index": "b23", + "isDeleted": false, + "id": "JLeWyU-nY4GTaTbokCB4O", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0.5971766580926774, + "x": 1869.984016418457, + "y": 817.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 74.03196716308594, + "height": 35, + "seed": 606588690, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704240284, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "mTLS", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "mTLS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 264, + "versionNonce": 2011333906, + "index": "b24", + "isDeleted": false, + "id": "B5mZoEqo5rupKbEGt_Ag9", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 5.571725482430848, + "x": 1829.984016418457, + "y": 535.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 56.30796813964844, + "height": 35, + "seed": 104988622, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718703988284, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "TLS", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "TLS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "diamond", + "version": 1630, + "versionNonce": 220147598, + "index": "b27", + "isDeleted": false, + "id": "bqV7kTrRiBNZ2F5Kdq9Vg", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2289.545454545455, + "y": 645, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 169.9090909090909, + "height": 110, + "seed": 303824590, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "qfCQA7tPmWivw4a_Yfc66" + }, + { + "id": "7vzj14HvSTh-ZzHuyp995", + "type": "arrow" + } + ], + "updated": 1718704148333, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1115, + "versionNonce": 686689742, + "index": "b28", + "isDeleted": false, + "id": "qfCQA7tPmWivw4a_Yfc66", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2341.9607308127665, + "y": 677.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 65.12399291992188, + "height": 45, + "seed": 1812919566, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704148333, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "IAS", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "bqV7kTrRiBNZ2F5Kdq9Vg", + "originalText": "IAS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "diamond", + "version": 1738, + "versionNonce": 2071436306, + "index": "b29", + "isDeleted": false, + "id": "t5N2kRSi-YYtRjskeeCbo", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2279.045454545455, + "y": 370, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 169.9090909090909, + "height": 110, + "seed": 1777002510, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "dUKWzmR1RwYtxTvh0G6DE" + }, + { + "id": "ad_YE9NYF8u5F7IG1nK_Y", + "type": "arrow" + } + ], + "updated": 1718704159311, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1224, + "versionNonce": 638470610, + "index": "b2A", + "isDeleted": false, + "id": "dUKWzmR1RwYtxTvh0G6DE", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2331.4607308127665, + "y": 402.5, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 65.12399291992188, + "height": 45, + "seed": 1420736078, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718704159311, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "IAS", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "t5N2kRSi-YYtRjskeeCbo", + "originalText": "IAS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2101, + "versionNonce": 275211854, + "index": "b2B", + "isDeleted": false, + "id": "ad_YE9NYF8u5F7IG1nK_Y", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2219.9999999999995, + "y": 421.4892488771416, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 59.51780515031123, + "height": 0.8434776429450608, + "seed": 731203342, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709626861, + "link": null, + "locked": false, + "startBinding": { + "elementId": "bC2ljiqjVxeq1dlCeoaRD", + "focus": -0.021127571682209308, + "gap": 1 + }, + "endBinding": { + "elementId": "t5N2kRSi-YYtRjskeeCbo", + "focus": 0.10093632898016605, + "gap": 3.398401442753027 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 59.51780515031123, + -0.8434776429450608 + ] + ] + }, + { + "type": "arrow", + "version": 2120, + "versionNonce": 1646149458, + "index": "b2C", + "isDeleted": false, + "id": "7vzj14HvSTh-ZzHuyp995", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2227.620196088758, + "y": 703.2305053038282, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 62.53645101925167, + "height": 1.6435423625475778, + "seed": 446462354, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1718709746973, + "link": null, + "locked": false, + "startBinding": { + "elementId": "Nzm-LhJpfzcT9cPslDLwi", + "focus": -0.00725725620488078, + "gap": 3.620196088758007 + }, + "endBinding": { + "elementId": "bqV7kTrRiBNZ2F5Kdq9Vg", + "focus": 0.011448986249751611, + "gap": 1 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 62.53645101925167, + -1.6435423625475778 + ] + ] + }, + { + "type": "diamond", + "version": 1742, + "versionNonce": 1780180046, + "index": "b2D", + "isDeleted": false, + "id": "n1xEiR98l4H-fVa649moS", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1574.4090909090912, + "y": 949.1818181818182, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 169.9090909090909, + "height": 110, + "seed": 1513015694, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "uiNDsy1J4hsw-Y5Rrhb43" + }, + { + "id": "09crasjK9WuDVn4zbUChd", + "type": "arrow" + }, + { + "id": "pR3GAnjODEcOFgemlLVVM", + "type": "arrow" + }, + { + "id": "48C5LDfRyY15oTkdsMuCc", + "type": "arrow" + } + ], + "updated": 1718709384577, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1225, + "versionNonce": 1038257614, + "index": "b2E", + "isDeleted": false, + "id": "uiNDsy1J4hsw-Y5Rrhb43", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1626.8243671764028, + "y": 981.6818181818182, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 65.12399291992188, + "height": 45, + "seed": 620390350, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1718709368870, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 1, + "text": "IAS", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "n1xEiR98l4H-fVa649moS", + "originalText": "IAS", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "ZwNVI5UVrzwWyrDXrq6DG", + "type": "text", + "x": 1557.5454545454543, + "y": 1064.1818181818178, + "width": 218.06390380859375, + "height": 35, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b2F", + "roundness": null, + "seed": 15791762, + "version": 105, + "versionNonce": 1197492558, + "isDeleted": false, + "boundElements": null, + "updated": 1718709424232, + "link": null, + "locked": false, + "text": "service instance", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "service instance", + "autoResize": true, + "lineHeight": 1.25 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/java/assets/java-ias.png b/java/assets/java-ias.png new file mode 100644 index 000000000..cb81e04c3 Binary files /dev/null and b/java/assets/java-ias.png differ diff --git a/java/security.md b/java/security.md index 93bf88770..4970eefd8 100644 --- a/java/security.md +++ b/java/security.md @@ -28,11 +28,13 @@ uacp: Used as link target from Help Portal at https://help.sap.com/products/BTP/ ## Overview -With respect to web services, authentication is the act of proving the validity of user claims passed with the request. This typically comprises verifying the user's identity, tenant, and additional claims like granted roles. Briefly, authentication controls _who_ is using the service. In contrast, authorization makes sure that the user has the required privileges to access the requested resources. Hence, authorization is about controlling _which_ resources the user is allowed to handle. +For Web services, authentication is about controlling _who_ is using the service. It typically involves verifying the user's identity, tenant, and validating claims like granted roles. In contrast, authorization makes sure that the user has the required privileges to access the requested resources. Hence, authorization is about controlling _what_ the user is allowed to handle. Hence both, authentication and authorization, are essential for application security: * [Authentication](#authentication) describes how to configure authentication. -* [Authorization](#auth) describes how to configure access control. +* [Authorization](#auth) is about resource access control. + +[Connecting to IAS Services](#outbound-auth) describes how to authenticate outbound calls. ::: warning Without security configured, CDS services are exposed to public. Proper configuration of authentication __and__ authorization is required to secure your CAP application. @@ -40,10 +42,19 @@ Without security configured, CDS services are exposed to public. Proper configur ## Authentication { #authentication} -User requests with invalid authentication need to be rejected as soon as possible, to limit the resource impact to a minimum. Ideally, authentication is one of the first steps when processing a request. This is one reason why it's not an integral part of the CAP runtime and needs to be configured on application framework level. In addition, CAP Java is based on a [modular architecture](./developing-applications/building#modular_architecture) and allows flexible configuration of the authentication method. For productive scenarios, [XSUAA and IAS](#xsuaa-ias) authentication is supported out of the box, but a [custom authentication](#custom-authentication) can be configured as well. For the local development and test scenario, there's a built-in [mock user](#mock-users) support. +Authentication rejects user requests with invalid authentication and limits the possible resource impact. + +Rejecting them as soon as possible is one of the reasons why it's not an integral part of the CAP runtime and needs to be configured on the application framework level. In addition, CAP Java is based on a [modular architecture](./developing-applications/building#modular_architecture) and allows flexible configuration of any authentication method. +By default, it supports the standard BTP platform identity services [out of the box](#xsuaa-ias): + +- [SAP Cloud Identity Services Identity Authentication (IAS)](https://help.sap.com/docs/cloud-identity-services) - preferred solution integrating endpoints cross SAP-systems +- [SAP Authorization and Trust Management Service (XSUAA)](https://help.sap.com/docs/authorization-and-trust-management-service) - previous offering scoped to a BTP landscape + +Which are highly recommended for production usage. For specific use cases, [custom authentication](#custom-authentication) can be configured as well. +Local development and testing can be done easily with built-in [mock user](#mock-users) support. ### Configure XSUAA and IAS Authentication { #xsuaa-ias} -To enable your application for XSUAA or IAS-authentication we recommend to use the `cds-starter-cloudfoundry` or the `cds-starter-k8s` starter bundle, which covers all required dependencies. +To enable your application for XSUAA or IAS-authentication, we recommend using the `cds-starter-cloudfoundry` or the `cds-starter-k8s` starter bundle, which covers all required dependencies. :::details Individual Dependencies These are the individual dependencies that can be explicitly added in the `pom.xml` file of your service: @@ -81,6 +92,11 @@ When authenticating incoming requests with IAS, the Proof-Of-Possession is activ You can disable the Proof-Of-Possession enforcement in your CAP Java application by setting the property `sap.spring.security.identity.prooftoken` to `false` in the `application.yaml` file. +:::tip +CAP Java requires an AppRouter to be configured with mTLS in case of IAS authentication (`forwardAuthCertificates: true`). +::: + + ### Automatic Spring Boot Security Configuration { #spring-boot} Only if **both, the library dependencies and an XSUAA/IAS service binding are in place**, the CAP Java SDK activates a Spring security configuration, which enforces authentication for all endpoints **automatically**: @@ -185,11 +201,12 @@ Another typical example is the configuration of [Spring Actuators](https://docs. public class ActuatorSecurityConfig { @Bean - public SecurityFilterChain actuatorFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain actuatorFilterChain(HttpSecurity http) + throws Exception { return http .securityMatcher(AntPathRequestMatcher.antMatcher("/actuator/**")) .httpBasic(Customizer.withDefaults()) - .authenticationProvider(/* configure basic authentication users here with PasswordEncoder etc. */) + .authenticationProvider(/* basic auth users with PasswordEncoder */) .authorizeHttpRequests(r -> r.anyRequest().authenticated()) .build(); } @@ -221,9 +238,10 @@ public class CustomUserInfoProvider implements UserInfoProvider { } } if (userInfo != null) { + /* any modification of the resolved user goes here: */ XsuaaUserInfo xsuaaUserInfo = userInfo.as(XsuaaUserInfo.class); userInfo.setName(xsuaaUserInfo.getEmail() + "/" + - xsuaaUserInfo.getOrigin()); // adapt name + xsuaaUserInfo.getOrigin()); // normalizes name } return userInfo; @@ -269,7 +287,6 @@ cds: mock: users: - name: Viewer-User - password: viewer-pass tenant: CrazyCars roles: - Viewer @@ -281,17 +298,17 @@ cds: - cruise - park - - name: Privileged-User - password: privileged-pass + - name: Admin-User + password: admin-pass privileged: true features: - "*" ``` ::: - Mock user with name `Viewer-User` is a typical business user with SaaS-tenant `CrazyCars` who has assigned role `Viewer` and user attribute `Country` (`$user.Country` evaluates to value list `[GER, FR]`). This user also has the additional attribute `email`, which can be retrieved with `UserInfo.getAdditionalAttribute("email")`. The [features](../java/reflection-api#feature-toggles) `cruise` and `park` are enabled for this mock user. -- `Privileged-User` is a user running in privileged mode. Such a user is helpful in tests that bypasses all authorization handlers. +- `Admin-User` is a user running in privileged mode. Such a user is helpful in tests that bypasses all authorization handlers. -Property `cds.security.mock.enabled = false` disables any mock user configuration. +Property `cds.security.mock.enabled = false` disables any mock user configuration (default in production profile). A setup for Spring MVC-based tests based on the given mock users and the CDS model from [above](#spring-boot) could look like this: @@ -340,6 +357,259 @@ cds: ::: The mock user `Alice` is assigned to the mock tenant `CrazyCars` for which the features `cruise` and `park` are enabled. + +## Connecting to IAS Services { #outbound-auth } + +CAP Java supports the consumption of IAS-based services of various kinds: + +* [Internal Services](#internal-app) bound to the same IAS instance of the provider application. +* [External IAS](#app-to-app) applications consumed by providing a destination. +* [BTP reuse services](#ias-reuse) consumed via service binding. + +![The TAM graphic is explained in the accompanying text.](./assets/java-ias.png){width="800px" } + +Regardless of the kind of service, CAP provides a [unified integration as Remote Service](/java/cqn-services/remote-services#remote-odata-services). +Basic communication setup and user propagation is addressed under the hood, for example, an mTLS handshake is performed in case of service-2-service communication. + +### Internal Services {#internal-app} + +For communication between adjacent CAP applications, these are CAP applications which are bound to the same identity instance, simplified configuration is explained in [Binding to a Service with Shared Identity](/java/cqn-services/remote-services#binding-to-a-service-with-shared-identity). + +### External Services (IAS App-to-App) {#app-to-app} + +CAP Java supports technical communication with any IAS-based service deployed to an SAP Cloud landscape. User propagation is supported. +For connection setup, it uses [IAS App-2-App flows](https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/consume-apis-from-other-applications). + +#### Provider Application + +The CAP Java application as a _provider app_ needs to: + +1. Configure [IAS authentication](/java/security#xsuaa-ias). +2. Expose an API in the IAS service instance. + + ::: details Sample IAS instance of provider (mta.yaml) + + Add this to your `mta.yaml` resources section: + + ```yaml + - name: server-identity + type: org.cloudfoundry.managed-service + parameters: + service: identity + service-plan: application + config: + multi-tenant: true + provided-apis: + - name: "review-api" + ``` + + ::: + +3. Prepare a CDS service endpoint for the exposed API. + + ::: details Sample CDS Service for the API + + ```cds + service ReviewService @(requires: 'review-api') { + [...] + } + ``` + + ::: + + +::: tip API as CAP role +The API identifiers exposed by the IAS instance in list `provided-apis` are granted as CAP roles after successful authentication. +::: + +::: warning Use different roles for technical and business users +Use different CAP roles for technical clients without user propagation and for named business users. + +Instead of using the same role, expose dedicated CDS services to technical clients which aren't accessible to business users and vice verse. +::: + +#### Consumer Application + +To set up a connection to such an IAS service, the _consumer app_ requires to do: + +1. Create an IAS instance that consumes the required API. + + ::: details Sample IAS instance for client (mta.yaml) + + Add this to your `mta.yaml` resources section: + + ```yaml + - name: client-identity + type: org.cloudfoundry.managed-service + parameters: + service: identity + service-plan: application + config: + multi-tenant: true + oauth2-configuration: + token-policy: + grant_types: + - "urn:ietf:params:oauth:grant-type:jwt-bearer" + ``` + + ::: + +2. Create a Remote Service based on the destination (optional). + ::: details Sample Remote Service configuration + + ```yaml + cds: + remote.services: + Reviews: + destination: + name: review-service-destination + ``` + + ::: + +To activate the App-2-App connection as a *consumer*, you need to: + +1. Create an IAS application dependency in the IAS tenant: + - Open the Cloud Identity Services admin console + - Navigate to [Application APIs / Dependencies](https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/communicate-between-applications) + - Create a new dependency pointing to your provider application's API + +2. Create a dedicated [destination](https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/access-destinations-editor) with the following configuration: + * The URL pointing to the IAS-endpoint of the application. + * Authentication type `NoAuthentication`. + * Attribute `cloudsdk.ias-dependency-name` with the name of the created IAS application dependency in Step 1. + +
+ + + +[Learn more about how to consume external application APIs with IAS](https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/consume-apis-from-other-applications) {.learn-more} + +[Learn more about simplified Remote Service configuration with destinations](/java/cqn-services/remote-services#destination-based-scenarios) {.learn-more} + + +### BTP Reuse Services {#ias-reuse} + +IAS-based BTP reuse services can be created/consumed with CAP Java even more easily. + +The CAP reuse service (provider) needs to: + +1. Configure [IAS authentication](/java/security#xsuaa-ias). +2. Bind an IAS instance that exposes services and service plans. + + ::: details Sample IAS instance for provider + + ```yaml + - name: server-identity + type: org.cloudfoundry.managed-service + parameters: + service: identity + service-plan: application + config: + multi-tenant: true + catalog: + services: + - id: "1d5c23ee-1ce6-6130-4af4-26461bc6ef79" + name: "review-service" + plans: + - id: "2d5c23ee-1ce6-6130-4af4-26461bc6ef78" + name: "review-api" + ``` + + ::: + +3. Prepare a CDS service endpoint for the exposed API. + + ::: details Sample CDS Service for the API + + ```cds + service ReviewService @(requires: 'review-api') { + [...] + } + ``` + + ::: + +The CAP consumer application (client) needs to: + +1. Create and bind the provided service from the marketplace. + + ::: details Create and bind service instance. + ```sh + cf create-service review-service review-api review-service-instance + cf bind-service review-service-instance --binding-name review-service-binding + ``` + ::: + +2. Create an IAS instance that consumes the required service. + + ::: details Sample IAS instance for client + + ```yaml + - name: client-identity + type: org.cloudfoundry.managed-service + parameters: + service: identity + service-plan: application + config: + multi-tenant: true + "consumed-services": [ { + "service-instance-name": "review-service-instance" + } ] + ``` + + ::: + +3. Create a Remote Service based on the binding (optional). + + ::: details Sample Remote Service configuration + + ```yaml + cds: + remote.services: + Reviews: + binding: + name: review-service-binding + onBehalfOf: currentUser + ``` + + ::: + +4. Use CQN queries to consume the reuse service (optional) + +[Learn more about simplified Remote Service configuration with bindings](/java/cqn-services/remote-services#service-binding-based-scenarios) {.learn-more} + +::: tip Service plan name as CAP role +The service plan names as specified in `consumed-services` in the IAS instance are granted as CAP roles after successful authentication. +::: + +::: warning Use different roles for technical and business users +Use different CAP roles for technical clients without user propagation and for named business users. + +Instead of using the same role, expose dedicated CDS services to technical clients which aren't accessible to business users and vice versa. +::: + + +#### How to Authorize Callbacks + +For bidirectional communication, callbacks from the reuse service to the CAP service need to be authorized as well. +Currently, there is no standadized way to achieve this in CAP so that custom codeing is required. +As a prerequisite*, the CAP service needs to know the clientId of the reuse service's IAS application which should be part of the binding exposed to the CAP service. + +::: details Sample Code for Authorization of Callbacks + +```java +private void authorizeCallback() { + UserInfo userInfo = runtime.getProvidedUserInfo(); + String azp = (String) userInfo.getAdditionalAttributes().get("azp"); + if(!userInfo.isSystemUser() || azp == null || !azp.equals(clientId)) { + throw new ErrorStatusException(ErrorStatuses.FORBIDDEN); + } + } +``` +::: + + ## Authorization { #auth} CAP Java SDK provides a comprehensive authorization service. By defining authorization rules declaratively via annotations in your CDS model, the runtime enforces authorization of the requests in a generic manner. Two different levels of authorization can be distinguished: @@ -353,7 +623,7 @@ A precise description of the general authorization capabilities in CAP can be fo In addition to standard authorization, CAP Java provides additional out of the box capabilities to reduce custom code: -#### Deep Authorization { #deep-auth} +### Deep Authorization { #deep-auth} Queries to Application Services are not only authorized by the target entity which has a `@restrict` or `@requires` annotation, but also for all __associated entities__ that are used in the statement. __Compositions__ are neither checked nor extended with additional filters. @@ -410,7 +680,7 @@ It can be disabled by setting cds.security.authorization.deep.enabl [Learn more about `@restrict.where` in the instance-based authorization guide.](/guides/security/authorization#instance-based-auth){.learn-more} -#### Forbidden on Rejected Entity Selection { #reject-403 } +### Forbidden on Rejected Entity Selection { #reject-403 } Entities that have an instance-based authorization condition, that is [`@restrict.where`](/guides/security/authorization#restrict-annotation), are guarded by the CAP Java runtime by adding a filter condition to the DB query **excluding not matching instances from the result**. @@ -428,7 +698,7 @@ It can be disabled by setting cds.security.authorization.instance-b [Learn more about `@restrict.where` in the instance-based authorization guide.](/guides/security/authorization#instance-based-auth){.learn-more} -#### Authorization Checks On Input Data { #input-data-auth } +### Authorization Checks On Input Data { #input-data-auth } Input data of `CREATE` and `UPDATE` events is also validated with regards to instance-based authorization conditions. Invalid input that does not meet the condition is rejected with response code `400`.