Simplify Security for Microservices on Converged Oracle Database -Part 1

Corrado De Bari
7 min readOct 3, 2022

--

With my colleagues Andy Tael, John Lathouwers and Fabrizio Zarri, we have recently released a new tutorial on Oracle LiveLabs named “Simplify Security for Microservices on Converged Oracle Database” to show step-by-step how to deploy a standalone ORDS (Oracle REST Data Services) server covering all aspects about security in a on Oracle Cloud Infrastructure.

ORDS offers several web-based services that provide development, data tools, administration, and monitoring features for Oracle Database, in Cloud and on-premises. But, the main features that we intend to exploit in a secure way in this architecture is the REST-Enabled SQL.

REST-Enabled SQL is a REST API that allows for ad-hoc SQL and SQL Scripts to be executed. You can POST one or more SQL statements to the service. The service then runs the SQL statements against Oracle Database and returns the results and output to the client in a JSON format. Oracle Database becomes a self-contained Microservices provider.

The OCI architecture we’ll implement in this paper is the following:

Deployment architecture on OCI

where we setup a standalone ORDS (Oracle REST Data Services) server in a secure way, protecting all the resources involved through a bastion services, a private end-point ADB-S database, an API Gateway, and monitoring the Autonomous DB with Oracle Data Safe. The workshop is intended to be run on a private OCI tenant in which you will deploy the infrastructure using Terraform (IaC) and expose a table in the ATP-S database using REST, which represents our Microservice.

This REST endpoint could be protected in 3 different ways:

  • First Party AuthN
  • Setup Third Party OAuth 2.0-Based AuthN
  • Three-Legged OAuth 2.0-Based AuthN

leveraging OAuth 2.0 capabilities available out-of-the box in ORDS, that could work as resource owner, authorization server and resource server, as shown in details here. All the ways have been described as steps to increase the level of security that you could apply to your ORDS based services, up to Three-Legged OAuth 2.0 that allow you to avoid sharing secrets with the clients, especially when your application is a pure Javascript web client.

These ORDS features, working together with the other services available on Oracle Cloud Infrastructure, allow to protect end-to-end the Microservices with an infrastructural approach.

In this first post we’ll describe the architecture without the API Gateway, with Load Balancer exposing straight the REST service, without any barrier to attack like denial of service, that could be prevented just by introducing in the middle the API Gateway service. The remaining elements of this architecture will be described in the next post.

But let’s deep dive into the first elements that you’ll find in this Lab available online.

All the resources needed to run this tutorial, in terms of Terraform/OCI-CLI shell scripts, pl/sql source code and so on it’s available on GitHub here.

Through the Terraform script provided, you will provision the foundation components of the architecture: ADB-S, ORDS on a compute instance, a Load Balancer and the Bastion Service to access via ssh the two main components secured in a private subnet. The reason why it isn’t used the ADB-S managed ORDS, it’s related first to exploit all the ORDS latest version capabilities in terms of security configuration, like adding new users, that are not allowed in the managed one. Secondly, it’s a way to show how to configure ORDS in an on-premises deployment scenarios.

Bastion service it’s the first infrastructural OCI security asset that you could use. It offers a managed service to create two kinds of sessions:

  • Managed SSH
  • SSH port forwarding

Terraform script will create one Managed SSH to connect ORDS compute node, and another one of SSH port forwarding session type to connect via sqlplus to ADB-S. In this way either module, even if in a private subnet not accessible from Internet, could be managed securely with fully managed service.

The Load Balancer has the security group, a sort of firewall rule, enabled to allow access to the ORDS instance, so it will be provided access to the Microservices without expose ORDS/ADB-S’s IP on Internet.

At this stage, let’s explore the three kinds of ORDS authentication we could put in place.

In AuthN First Party ORDS authentication, the steps to secure a REST service exposed are (via PL/SQL):

  • create a role with: ORDS.CREATE_ROLE()
  • create a privilege for the role created: ORDS.CREATE_PRIVILEGE()
  • associate privilege to resources exposed: ORDS.CREATE_PRIVILEGE_MAPPING()
  • the resource is no more accessible until we add a user to the role created, with a command line statement:
$ ords — config /home/oracle/ords/config config user add <user> <role>

After that, the resources will be available via curl in this way:

$ curl -i -k — user <user>:<password> https://${LB}/ords/ordstest/examples/employees/

Third Party OAuth 2.0-Based AuthN allow us to avoid the authentication via user ID and password, replacing the credential to provide with a pair of CLIENT_ID and CLIENT_SECRET generated, and getting an Authorization code that will expire. You can think of them as the userid and password for the client application.

The steps to setup this kind of authentication are:

  • with OAUTH.CREATE_CLIENT() PL/SQL function, providing in input the privilege, it will create in table user_ords_clients credentials like these:
CLIENT_ID                CLIENT_SECRET— — — — — — — — — — — — — — — — — — — — — — — — MyskbM4pxgB4Q1U00Ui99g.. PAAbXI6wdzb_m0DcIi6Zxg..
  • OAUTH.GRANT_CLIENT_ROLE() PL/SQL function grant a required role, like in this example:
BEGIN
OAUTH.CREATE_CLIENT(
p_name => ‘Client Credentials Example’
,p_grant_type => ‘client_credentials’
,p_privilege_names => ‘example.employees’
,p_support_email => ‘support@example.com’
);
COMMIT;
END;
/

After that, the authorization token will be available via curl in this way:

$ curl -k -0 -i — user <CLIENT_ID>:<CLIENT_SECRET> — data “grant_type=client_credentials” https://${LB}/ords/ordstest/oauth/token

and the response will looks like:

{“access_token”:”eUSBOqI47Pt7jI_hmfJjPQ”,”token_type”:”bearer”,”expires_in”:3600}

Finally, we’ll access to the resource in this way:

$ curl -k -0 -i -H”Authorization: Bearer <ACCESS_TOKEN>” https://${LB}/ords/ordstest/examples/employees/

Three-Legged OAuth 2.0-Based AuthN flows involve three parties: the party calling the RESTful API, the party providing the RESTful API, and an end user party that owns or manages the data to which the RESTful API provides access. Three-legged flows are used in client to server interactions where an end user must approve access to the RESTful API. In OAuth 2.0 the authorization code flow and the implicit flow are three-legged flows. These flows are typically used in business to consumer scenarios. All the process is managed by ORDS itself.

The setup involves these steps:

  • OAUTH.CREATE_CLIENT() PL/SQL function again:
BEGIN
OAUTH.CREATE_CLIENT(
p_name => ‘Authorization Code Example’
,p_grant_type => ‘authorization_code’
,p_owner => ‘Example Inc.’
,p_description => ‘Sample for demonstrating Authorization Code Flow’
,p_redirect_uri => ‘http://[LOADBALANCER_IP]/auth/code/example/'
,p_support_email => ‘support@example.org’
,p_support_uri => ‘http://example.org/support'
,p_privilege_names => ‘example.employees’
);
COMMIT;
END;
/

but:

  • p_grant_type is of type ‘authorization_code’ ;
  • p_redirect_uri defines where redirect after authentication, and it will include the authorization code in the query string portion of the URI.

The results will be new credentials like:

ID    CLIENT_ID                CLIENT_SECRET— — — — — — — — — — — — — — — — — — — — — — — — — — — 10046 aFsQ76cbIBG2mBFw_EtcTA.. QH9yBVdzg2fUL7rr0FUEDQ..

created in user_ords_clients table.

In this case, the access it will be performed necessarily through a web browser, because we need the interaction with the users to generate a temporary token without sharing credentials at any time with the application needs to access the resources.

Asking for the resource providing only the <CLIENT_ID>, with an URI like this:

https://[LOADBALANCER_IP]/ords/ordstest/oauth/auth?response_type=code&client_id="<CLIENT_ID>"&state=3668D7A713E93372E0406A38A8C02171

the response will be “Unauthorized”, with a link for Sign In:

Unauthorized response from ORDS Authorization service

If the CLIENT_ID is recognized, then a sign in prompt is displayed. You will enter the credentials of the user registered in Role and associated via privilege mapping to the resources, and click Sign In:

Provide user credential to the Authorization service

On the next page click Approve:

Page to grant authorization to access the resource to a third party

This will cause a redirect to redirect URI specified when the client was registered. The redirect URI will include the authorization code in the query string portion of the URI. It will also include the same state parameter value that the client provided at the start of the flow. The redirect URI will look like the following:

http://[LOADBALANCER_IP]/auth/code/example/?code=Y7ue-kEO7jZV6HgLU4vkaw&state=3668D7A713E93372E0406A38A8C02171

The client application must verify the value of the state parameter if it matches with the initial one provided, and then note the value of the code parameter, which will be used in to obtain an access token.

Now the client can get a temporary authorization code from the authorization server (ORDS) to provide to the resource server (ORDS itself):

$ curl -k -0 — user <CLIENT_ID>:<CLIENT_SECRET> — data “grant_type=authorization_code&code=<AUTHORIZATION_CODE>” https://${LB}/ords/ordstest/oauth/token

As in Third Party OAuth 2.0-Based authentication, the response it will be a temporary access token:

{“access_token”:”L-RxBvjACN-F029kIv-5qQ”,”token_type”:”bearer”,”expires_in”:3600,”refresh_token”:”z2_ToaMJOiW6JiBav7zzLQ”}

that could be used to access the REST service:

curl -k -0 -i -H”Authorization: Bearer <ACCESS_TOKEN>” https://${LB}/ords/ordstest/examples/employees/

This concludes the first part of the description of the lab. Coming soon the second part with the configuration of the Gateway API of the DataSafe service.

Disclaimer

The views expressed in this paper are my own and do not necessarily reflect the views of Oracle.

--

--