Securing the Generated Service¶
Consider adding security measures to your generated OData service to control access.
You can secure the generated OData services by:
-
Authenticating each user's identity.
-
Authorizing each user's data access.
-
Ensuring the confidentiality of data that's passed over the network.
Caution
If you omit the -login
option during service generation, the
generated OData service doesn't check a user's identity or restrict a user's data access. Nor does it guarantee that
data passed over the network is encrypted (via HTTPS). Apart from exceptional circumstances, such as public-access
read-only services, you should configure a production application for authentication, authorization, and
confidentiality. This helps to ensure compliance with the EU General Data Protection
Regulation or other applicable regulations.
Authentication¶
Using the -login
option, specify XSUAA
for Cloud Foundry
(or another option supported by the target environment) to ensure that only authenticated users can access the service, it also supports X509
for Principal Propagation authentication for on-premise server.
Note
The generated service uses the login-config
element within the generated web.xml
to enforce authentication, however,
for X509
authentication the login-config
element will not be added (a servlet filter will be generated in that case).
Authorization¶
Specify the Security.Roles
annotation for security roles that might not be referenced in other security annotations,
but might be referenced in runtime checks using custom code, for example, when you are implementing
row-level authorization.
Specify the Security.ServiceUserRoles
annotation (or rely on the default Everyone
role which matches all authenticated users)
to ensure that only authorized users will be able to access the main OData service
To authorize a subset of all authenticated users, specify a role name such as ServiceUser
.
Specify the Security.ViewMetricsRoles
annotation (or rely on the default ViewMetrics
role) to ensure that only
authorized administrators can access the embedded metrics service.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.sql.v1.xml">
<edmx:Include Alias="Security" Namespace="com.sap.cloud.server.odata.security.v1"/>
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="example" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Self">
...
<EntityContainer Name="ExampleService">
<Annotation Term="Security.Roles">
<Collection>
<String>Manager</String>
</Collection>
</Annotation>
<Annotation Term="Security.ServiceUserRoles">
<Collection>
<String>Employee</String>
</Collection>
</Annotation>
<Annotation Term="Security.ViewMetricsRoles">
<Collection>
<String>Administrator</String>
</Collection>
</Annotation>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Note
The generated service uses security-constraint
elements within the generated web.xml
to enforce authorization.
Fine-Grained Authorization¶
All authorized users have permission to create, read, update, and delete any data. The following section describe how to achieve more fine-grained authorization controls.
Method-Level Authorization¶
Reference the Security
annotation vocabulary in the CSDL XML file to restrict access to data methods (action imports,
function imports), and apply the Security.InvokeRoles
annotation term from that vocabulary to the data methods.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.sql.v1.xml">
<edmx:Include Alias="Security" Namespace="com.sap.cloud.server.odata.security.v1"/>
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="example" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Self">
...
<Action Name="SetSalaryAction">
...
</Action>
<EntityContainer Name="ExampleService">
...
<ActionImport Name="SetSalary" Action="Self.SetSalaryAction">
<Annotation Term="Security.InvokeRoles">
<Collection>
<String>Manager</String>
</Collection>
</Annotation>
</ActionImport>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
A user needs only one of the permitted roles to be allowed access. Specifying an empty roles collection in the roles annotation means nobody can access the resource.
Table-Level Authorization¶
Reference the Security
annotation vocabulary in the CSDL XML file to restrict access to entity sets (database tables)
and apply the annotation terms from that vocabulary to the entity sets.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference Uri="vocabularies/com.sap.cloud.server.odata.sql.v1.xml">
<edmx:Include Alias="Security" Namespace="com.sap.cloud.server.odata.security.v1"/>
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="example" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="Self">
...
<EntityType Name="Customer">
...
</EntityType>
<EntityType Name="Order">
...
</EntityType>
<EntityContainer Name="ExampleService">
<EntitySet Name="Customers" EntityType="Self.Customer">
<Annotation Term="Security.ReadRoles">
<Collection>
<String>ViewCustomer</String>
</Collection>
</Annotation>
<Annotation Term="Security.WriteRoles">
<Collection>
<String>EditCustomer</String>
</Collection>
</Annotation>
<NavigationPropertyBinding Path="Orders" Target="Orders"/>
</EntitySet>
...
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Available annotation terms for entity set security include the following:
-
Security.ReadWriteRoles
– a collection of roles permitted for read or write access, if not overridden by the more specificSecurity.ReadRoles
,Security.WriteRoles
,Security.CreateRoles
,Security.UpdateRoles
orSecurity.DeleteRoles
. -
Security.ReadRoles
– a collection of security roles permitted for read access. -
Security.WriteRoles
– a collection of security roles permitted for write access, if not overridden by the more specificSecurity.CreateRoles
,Security.UpdateRoles
, orSecurity.DeleteRoles
.
In each case, a user needs only one of the permitted roles to be allowed access. Specifying an empty roles collection in
the roles annotation means nobody can access the resource. Additionally specifying the Security.ReadRoles
, but not the
Security.WriteRoles
, causes nobody to have write access except as permitted by Security.CreateRoles
,
Security.UpdateRoles
, or Security.DeleteRoles
.
Row-Level Authorization¶
You may want to customize generated listener classes to implement row-level authorization. The simplest way to achieve
this is to add code into a beforeQuery
listener method to add extra filter conditions to the client-specified queries.
Adding these query filters also prevents write access to the respective records.
For example, suppose there is an Employee
entity type with a business rule that managers can access any employee's
record, but regular employees can access only their own employee record. This might be coded in the EmployeeListener
class.
@Override void beforeQuery(DataQuery query)
{
if (!servlet.isUserInRole("Manager"))
{
// Add or extend query filter to employee's own record only.
query.filter(Employee.email.equal(servlet.currentUser()));
}
}
If it isn't feasible to add extra filter conditions to achieve the required level of row-level authorization, then you
may need to customize the executeQuery
method in the generated entity handler for the entity type to post-process
the query results.
Note
Any security role name used in a servlet.isUserInRole
check must reference at least one security roles
annotation so that the role name is known at deployment time. Use the Security.Roles
annotation, as shown in the
authorization examples, if there are no other roles-related annotations that reference the required role name.
Column-Level Authorization¶
Customize generated listener classes to implement column-level authorization.
For example, suppose that only managers can update an employee's salary, but employees can update other details in their
own employee records. In addition to the beforeQuery
customization, this might be coded in the EmployeeListener
class.
@Override void beforeSave(EntityValue entityValue)
{
Employee entity = (Employee)entityValue;
if (entity.isNewOrChanged(Employee.salary)
&& !servlet.isUserInRole("Manager"))
{
throw AccessDeniedException.cannotWrite(Employee.salary.getQualifiedName());
}
}
Note
Any security role name used in a servlet.isUserInRole
check must reference at least one security roles
annotation so that the role name is known at deployment time. Use the Security.Roles
annotation, as shown in the
authorization examples, if there are no other roles-related annotations referencing the required role name.
Confidentiality¶
Using the -login
option ensures the confidentiality of data passed over the network.
Note
The generated service uses the transport-guarantee
element of CONFIDENTIAL
within the generated web.xml
to achieve confidentiality.
Local Apache TomEE Security¶
Please refer to the Apache TomEE Security documentation and Apache Tomcat Security documentation for detailed configuration instructions.
-
Edit
conf/tomcat-users.xml
to create users and assign appropriate roles. -
Your OData service should now be ready for secure access by regular users and administrators. Make sure to use an
https
URL when connecting.
Note: A local server is useful for basic security testing, but additional security testing should always be performed in the intended target environment.
See also: -http
and -https
options.
SAP Business Technology Platform Security¶
Use the security provided by the SAP Business Technology Platform to secure your generated OData service.
Note
The Develop Applications topic in the SAP Business Technology Platform documentation is a good starting point for additional information about SAP Business Technology Platform security.
SAP Business Technology Platform Security – Quick Setup¶
The MBT: Create tasks.json file command should have created
a Visual Studio Code Task labeled setup-mobile-app
which can setup
the Mobile Application and Mobile Destination for secure mobile client connectivity.
Use Terminal > Run Task > setup-mobile-app
in Visual Studio Code or SAP Business Application Studio.
In certain situations this task may request some additional manual steps to be taken.
Configure Role Collections
and Trust Configuration
as documented in the next section.
See Cloud Connector Setup for Mobile Clients for local or on-premise deployments.
SAP Business Technology Platform Security – Mobile Services¶
Use these security measures to keep your application secure in the SAP Mobile Services - Cloud Foundry environment.
The following instructions refer to the SAP Mobile Services Cockpit, and are subject to change if the cockpit UI changes.
SAP Business Technology Platform for Cloud Foundry usually requires a xsuaa
service instance and application router creation in
order to secure a deployed Java application. This is described in the next section. If deployed OData services are to be consumed by mobile
applications and SAP Mobile Services for Cloud Foundry is available, the process can be simplified to
the following steps.
-
Using the SAP Mobile Services Cockpit, select
Mobile Applications > Native/Hybrid > New
. -
For
ID
andName
, enter the-application
name that was selected for service generation. -
On the
Info
tab for your mobile application, select the+
sign to the right ofAssigned Features
. ChooseMobile Connectivity
and selectOK
. -
On the Mobile Connectivity
Configuration
tab, select theCreate
icon to create a destination. -
Enter your OData service root URL, then select
No Rewriting
as the rewrite mode. -
Skip the
Custom Headers
andAnnotations
dialog pages. -
Select
Forward Authentication
as the SSO mechanism, then selectFinish
. -
On the
APIs
tab for your mobile application, note theDestination
URL, which is the URL that clients should use to access your OData service with authentication. Note that any attempts by clients to directly access the OData service (other than via theDestination
URL) will encounter HTTP error401
. -
On the
Security
tab for your mobile application, select theEdit
(pencil) icon to the right ofApplication Settings
and choose the security configuration (Basic
,SAML
, orOAuth
) that meets your organization's security requirements. You may be able to useBasic
for testing purposes depending on your identity provider service.SAML
works well with desktop browser clients. UsingOAuth
may require more client-side configuration. -
On the
Security
tab for your mobile application, select theEdit
(pencil) icon to the right ofXSUAA Settings
. SelectBrowse
to open thexs-security.json
file from your application's project folder. -
Select
OK
to save the role settings. -
Consult the SAP Business Technology Platform documentation
Security > Authorization and Trust Management > Developing Security Artifacts > Set Up Security Artifacts > Bind the XSUAA Service Instance to the Application
. Bind the<app-name>-xsuaa
service instance to your OData service. -
Restart your OData service so it recognizes the assigned
xsuaa
service instance. -
In the SAP Business Technology Platform Cockpit, navigate to your Cloud Foundry subaccount, then use
Security > Role Collections
to define one or more role collections. If your application uses the defaultServiceUser
andViewMetrics
roles, define a role collection for each one and add the corresponding role to it. Otherwise, define role collections in accordance with the roles you selected using OData annotations for authorization. For each roleServiceUser
andViewMetrics
, highlight the role. SelectAssign
and in the pop-up specify your user id and selectAssign
. TheServiceUser
role is for regular users of the service (that is, a regular user of the service must have this role in order to be permitted to use the service, unless theEveryone
role has been enabled by default during service deployment). TheViewMetrics
role is for administrators who want to view the service’s performance metrics. Regular users should not be permitted to view the metrics. -
In the SAP Business Technology Platform Cockpit, navigate to your Cloud Foundry subaccount, then select
Security > Trust Configuration
and select your identity provider to show theRole Collection Assignment
page, where you can assign role collections to individual users. You may also need to edit the trust configuration namedtrust_mobile_services
, and disable theAvailable for User Login
option.
SAP Business Technology Platform Security – Cloud Foundry¶
Use these security measures to keep your application secure in the SAP Business Technology Platform - Cloud Foundry environment.
The following instructions refer to the SAP Business Technology Platform Cockpit, and are subject to change if the cockpit UI changes.
-
Consult the SAP Business Technology Platform documentation topic
Security > Authorization and Trust Management > Authorization and Trust Management in the Cloud Foundry Environment
. -
Using the SAP Business Technology Platform Cockpit, navigate to your Cloud Foundry space, then use the
Service Marketplace
menu option to locate thexsuaa
service. -
Select the
xsuaa
service, then selectInstances
, and selectNew Instance
. -
In the
Specify Parameters
page of the wizard, selectBrowse
and select thexs-security.json
file that was generated in your project folder. This file defines the scopes and roles that are needed by the application. -
On the
Assign Application
page of the wizard, choose your deployed application. -
On the
Confirm
page of the wizard, choose an instance name (for example:my-app-xsuaa
) and selectFinish
. -
Restart your OData service so it can recognize the assigned
xsuaa
service instance. -
Consult the SAP Business Technology Platform documentation
Development > Applications in the Cloud Foundry Environment > Configure Application Router
. -
Consult the SAP Business Technology Platform documentation
Security > Authorization and Trust Management > Developing Security Artifacts > Set Up Security Artifacts > Bind the XSUAA Service Instance to the Application
. Bind thexsuaa
service instance to your application router (it was already bound to your OData service by the priorAssign Application
step). Restart your application router. -
Configure
Role Collections
andTrust Configuration
as documented in the previous section.
This following additional information may be helpful as you set up XSUAA:
-
When you create your service
xsuaa
instance make sure to specifyapplication
as the plan. -
The generated
xs-security-json
defaults todedicated
as the tenant mode. Some Cloud Foundry landscape IDPs configure for "shared" tenant-mode. In that case, change it toshared
before creating the XSUAA service instance. -
In SAP Business Technology Platform Cockpit, the
Trust Configuration
andRole Collections
require security administrator privileges, otherwise you can't see them.Your OData service is now ready for secure access by regular users and administrators.
Cloud Connector Setup for Mobile Clients¶
This section is only relevant for local or on-premise deployments of the generated OData service.
Once the SAP Business Technology Platform Security setup has been completed,
there should exist in the SAP Mobile Services account a Mobile/Native application named <app-name>
,
and a Mobile Destination named app
(or similar).
If the OData service was deployed locally (or on-premise), then the Mobile Destination should have the
Use Cloud Connector
checkbox enabled and should have a URL
of the form http://<virtual-host>:<virtual-port>
.
The recommended <virtual-host>
is the <app-name>
with all underscores ('_') replaced with hyphens ('-').
For example, if the <app-name>
is my_app
, then the <virtual-host>
should be my-app
.
The recommended <virtual-port>
is 80
.
Set up SAP Cloud Connector with the selected Virtual Host
name (e.g. my-app
) and Virtual Port
number (e.g. 80
)
and an Internal Host
name and Internal Port
number that match the local or on-premise host name and port number of the deployed OData service.
X509 Principal Propagation Authentication¶
Using the -login
option specify X509
to enable Principal Propagation authentication.
Note
This option only supports an on-premise OData service.
In this scenario, it will setup Mutual Authentication
between the SAP Cloud Connector and the on-premise OData service, however the on-premise OData service does not validate the Common Name from the client certificate. The SAP Cloud Connector will put a temporary user certificate in the HTTP request header ssl_client_cert
, which contains the identity of an on-demand user. A filter in the on-premise OData service will decode this header and put the identity to the User Principal.
The following instructions are to configure the Principal Propagation
authentication in SAP Mobile Services, SAP Cloud Connector and the on-premise OData service.
-
Firstly, configure the SAP Mobile Services. Create a new Application in
Native/Hybrid
Mobile Applications and assign theMobile Connectivity
feature, create a newMobile Destination
in theMobile Connectivity
feature, theSSO Mechanism/Authentication
should be set toSAP Cloud Connector SSO
in theMobile Destination
, for more information please refer to:- Defining Connectivity (SAP Mobile Services (Cloud Foundry environment))
-
Secondly, configure the SAP Cloud Connector, setup trusts between SAP Business Technology Platform and SAP Cloud Connector, also setup the trusts between SAP Cloud Connector and back-end server, add corresponding
Subaccount
, configure theAccess Control
inCloud To On-Premise
section, for more information please refer to:- Connectivity (SAP Business Technology Platform Connectivity (Cloud Foundry environment))
-
Finally, setup the
Mutual Authentication
in the on-premise OData service, for more information please refer to the server documentation (e.g. for Apache Tomcat or TomEE).