Loading Data from
Multi-Cloud Storage to Oracle Database
Including Oracle
Object Storage, Azure Blob Storage and AWS S3
Part 1: Deploying
DBMS_CLOUD Package
Author: Donatien MBADI OUM, Oracle Consultant
1.
Introduction
A multicloud environment is one where
an enterprise uses more than one cloud platform (with at least two or more
public clouds) that each delivers a specific application or service. A
multicloud combines on-premise operations with services and applications
running on multiple public cloud providers, which enables organizations to
capture the benefits of each platform while mitigating their downsides.
While using resources from multiple
cloud vendors, you usually deal with migrating data across the environments or
keeping it on one cloud environment while accessing it from another. The Oracle
DBMS_CLOUD is cloud native package which allows you to access data on OCI
Object Storage, Azure Blob Storage and Amazon S3 buckets and import it into an
Oracle Database from these sources. DBMS_CLOUD package is pre-installed,
configured and maintained in Oracle Autonomous database.
In this article, we are going first to
describe the steps to manually install this package on Non-Autonomous Database
including on-premise Oracle Database, DBCS, Oracle Exadata Public Cloud
Database and Exadata Cloud@Customer Database. This package is supported in Oracle Database
19c beginning with 19.9 and in Oracle database 21c beginning with 21.3.
To ensure proper installation of DBMS_CLOUD into any existing and future pluggable database, you need to use catcon.pl. Create a script called dbms_cloud_install.sql which will consists to install DBMS_CLOUD owned by schema called C##CLOUD$SERVICE. You must log as SYS or SYSTEM on the root container.
$vi dbms_cloud_install.sql
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
set verify off
-- you must not change the
owner of the functionality to avoid future issues
define username='C##CLOUD$SERVICE'
create user &username no
authentication account lock;
REM Grant Common User Privileges
grant INHERIT PRIVILEGES on user &username to sys;
grant INHERIT PRIVILEGES on user sys to &username;
grant RESOURCE, UNLIMITED TABLESPACE, SELECT_CATALOG_ROLE to &username;
grant CREATE ANY TABLE, DROP ANY TABLE, INSERT ANY TABLE, SELECT ANY TABLE,
CREATE ANY CREDENTIAL, CREATE PUBLIC SYNONYM, CREATE PROCEDURE, ALTER SESSION,
CREATE JOB to &username;
grant CREATE SESSION, SET CONTAINER to &username;
grant SELECT on SYS.V_$MYSTAT to &username;
grant SELECT on SYS.SERVICE$ to &username;
grant SELECT on SYS.V_$ENCRYPTION_WALLET to &username;
grant read, write on directory DATA_PUMP_DIR to &username;
grant EXECUTE on SYS.DBMS_PRIV_CAPTURE to &username;
grant EXECUTE on SYS.DBMS_PDB_LIB to &username;
grant EXECUTE on SYS.DBMS_CRYPTO to &username;
grant EXECUTE on SYS.DBMS_SYS_ERROR to &username;
grant EXECUTE ON SYS.DBMS_ISCHED to &username;
grant EXECUTE ON SYS.DBMS_PDB_LIB to &username;
grant EXECUTE on SYS.DBMS_PDB to &username;
grant EXECUTE on SYS.DBMS_SERVICE to &username;
grant EXECUTE on SYS.DBMS_PDB to &username;
grant EXECUTE on SYS.CONFIGURE_DV to &username;
grant EXECUTE on SYS.DBMS_SYS_ERROR to &username;
grant EXECUTE on SYS.DBMS_CREDENTIAL to &username;
grant EXECUTE on SYS.DBMS_RANDOM to &username;
grant EXECUTE on SYS.DBMS_SYS_SQL to &username;
grant EXECUTE on SYS.DBMS_LOCK to &username;
grant EXECUTE on SYS.DBMS_AQADM to &username;
grant EXECUTE on SYS.DBMS_AQ to &username;
grant EXECUTE on SYS.DBMS_SYSTEM to &username;
grant EXECUTE on SYS.SCHED$_LOG_ON_ERRORS_CLASS to &username;
grant SELECT on SYS.DBA_DATA_FILES to &username;
grant SELECT on SYS.DBA_EXTENTS to &username;
grant SELECT on SYS.DBA_CREDENTIALS to &username;
grant SELECT on SYS.AUDIT_UNIFIED_ENABLED_POLICIES to &username;
grant SELECT on SYS.DBA_ROLES to &username;
grant SELECT on SYS.V_$ENCRYPTION_KEYS to &username;
grant SELECT on SYS.DBA_DIRECTORIES to &username;
grant SELECT on SYS.DBA_USERS to &username;
grant SELECT on SYS.DBA_OBJECTS to &username;
grant SELECT on SYS.V_$PDBS to &username;
grant SELECT on SYS.V_$SESSION to &username;
grant SELECT on SYS.GV_$SESSION to &username;
grant SELECT on SYS.DBA_REGISTRY to &username;
grant SELECT on SYS.DBA_DV_STATUS to &username;
alter session set
current_schema=&username;
REM Create the Catalog objects
@$ORACLE_HOME/rdbms/admin/dbms_cloud_task_catalog.sql
@$ORACLE_HOME/rdbms/admin/dbms_cloud_task_views.sql
@$ORACLE_HOME/rdbms/admin/dbms_cloud_catalog.sql
@$ORACLE_HOME/rdbms/admin/dbms_cloud_types.sql
REM Create the Package Spec
@$ORACLE_HOME/rdbms/admin/prvt_cloud_core.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_task.plb
@$ORACLE_HOME/rdbms/admin/dbms_cloud_capability.sql
@$ORACLE_HOME/rdbms/admin/prvt_cloud_request.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_internal.plb
@$ORACLE_HOME/rdbms/admin/dbms_cloud.sql
@$ORACLE_HOME/rdbms/admin/prvt_cloud_admin_int.plb
REM Create the Package Body
@$ORACLE_HOME/rdbms/admin/prvt_cloud_core_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_task_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_capability_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_request_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_internal_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_body.plb
@$ORACLE_HOME/rdbms/admin/prvt_cloud_admin_int_body.plb
-- Create the metadata
@$ORACLE_HOME/rdbms/admin/dbms_cloud_metadata.sql
alter session set current_schema=sys;
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
Assuming you create a script in a working directory dbc under the home directory /home/oracle, the command would like as follows:
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/<your_sys_password> --force_pdb_mode 'READ WRITE' -b dbms_cloud_install -d /home/oracle/dbc -l /home/oracle/dbc dbms_cloud_install.sql
Check that the package is created and
valid in both root and any PDB:
REM from within ROOT to see all containers
select con_id, owner, object_name, status, sharing, oracle_maintained from cdb_objects
where object_name = 'DBMS_CLOUD' order by con_id;
REM within an individual container only
select owner, object_name, status, sharing, oracle_maintained from dba_objects
where object_name = 'DBMS_CLOUD'
2.2.Step 2: Create SSL Wallet with Certificates
In order to safely access HTTP URIs and Object Stores, a wallet is required
with appropriate certificates for the objects stores. Run the following command
to download the certificates:
wget https://objectstorage.us-phoenix-1.oraclecloud.com/p/QsLX1mx9A-vnjjohcC7TIK6aTDFXVKr0Uogc2DAN-Rd7j6AagsmMaQ3D3Ti4a9yU/n/adwcdemo/b/CERTS/o/dbc_certs.tar
-
Move the certificates to the wallet location
-
Untar the certificates tar file
…
…
-
Create the wallet and add the certificates to the wallet
$ orapki wallet create -wallet . -pwd <PASSWORD> -auto_login
$ orapki wallet add -wallet . -trusted_cert -cert /opt/oracle/dcs/commonstore/wallets/ssl/VeriSign.cer -pwd <PASSWORD>
$ orapki wallet add -wallet . -trusted_cert -cert /opt/oracle/dcs/commonstore/wallets/ssl/BaltimoreCyberTrust.cer -pwd <PASSWORD>
$ orapki wallet add -wallet . -trusted_cert -cert /opt/oracle/dcs/commonstore/wallets/ssl/DigiCert.cer -pwd <PASSWORD>
-
Create an entry in sqlnet.ora file to use the wallet file
2.3.Step 3: Configure the database with
ACEs for DBMS_CLOUD
Create Access Control Entries (ACEs) to allow communication with Object
Stores through https.
Create a script called dbc_access.sql and execute as SYS or SYSTEM on the root container.
$vi dbc_access.sql
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
-- you must not change the owner of the
functionality to avoid future issues
define clouduser=C##CLOUD$SERVICE
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE
PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory
define sslwalletdir=<Set SSL Wallet Directory>
--
-- UNCOMMENT AND SET THE PROXY SETTINGS VARIABLES IF YOUR ENVIRONMENT NEEDS
PROXYS
--
-- define proxy_uri=<your proxy URI address>
-- define proxy_host=<your proxy DNS name>
-- define proxy_low_port=<your_proxy_low_port>
-- define proxy_high_port=<your_proxy_high_port>
-- Create New ACL / ACE s
begin
-- Allow all hosts for HTTP/HTTP_PROXY
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 443,
upper_port => 443,
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
--
-- UNCOMMENT THE PROXY SETTINGS SECTION IF YOUR ENVIRONMENT NEEDS PROXYS
--
-- Allow Proxy for HTTP/HTTP_PROXY
-- dbms_network_acl_admin.append_host_ace(
-- host =>'&proxy_host',
-- lower_port => &proxy_low_port,
-- upper_port => &proxy_high_port,
-- ace => xs$ace_type(
-- privilege_list => xs$name_list('http', 'http_proxy'),
-- principal_name => upper('&clouduser'),
-- principal_type => xs_acl.ptype_db));
--
-- END PROXY SECTION
--
-- Allow wallet access
dbms_network_acl_admin.append_wallet_ace(
wallet_path => 'file:&sslwalletdir',
ace => xs$ace_type(privilege_list =>
xs$name_list('use_client_certificates', 'use_passwords'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
end;
/
-- Setting SSL_WALLET database property
begin
-- comment out the IF block when installed in non-CDB environments
if sys_context('userenv', 'con_name') = 'CDB$ROOT' then
execute immediate 'alter database property set
ssl_wallet=''&sslwalletdir''';
--
-- UNCOMMENT THE FOLLOWING COMMAND IF YOU ARE USING A PROXY
--
-- execute immediate 'alter database property set
http_proxy=''&proxy_uri''';
end if;
end;
/
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
You
can check the proper setup of your database properties
2.4.Step 4: Verify configuration of
DBMS_CLOUD
Now,
you need to verify the proper setup of the SSL Wallet and the ACEs. Create a
script named test_dbms_cloud.sql and execute it as SYS or SYSTEM
either within the CDB or any PDB.
$vi test_dbms_cloud.sql
-- you must not change the owner of the functionality
to avoid future issues
define clouduser=C##CLOUD$SERVICE
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE
PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory and password
define sslwalletdir=<Set SSL Wallet
Directory>
define sslwalletpwd=<Set SSL Wallet
password>
-- create and run this procedure as owner
of the ACLs, which is the future owner
-- of DBMS_CLOUD
CREATE OR REPLACE PROCEDURE &clouduser..GET_PAGE(url IN VARCHAR2) AS
request_context UTL_HTTP.REQUEST_CONTEXT_KEY;
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
data VARCHAR2(32767) default null;
err_num NUMBER default 0;
err_msg VARCHAR2(4000) default null;
BEGIN
-- Create a request context with its
wallet and cookie table
request_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(
wallet_path => 'file:&sslwalletdir',
wallet_password => '&sslwalletpwd');
-- Make a HTTP request using the private
wallet and cookie
-- table in the request context
req := UTL_HTTP.BEGIN_REQUEST(
url => url,
request_context => request_context);
resp := UTL_HTTP.GET_RESPONSE(req);
DBMS_OUTPUT.PUT_LINE('valid response');
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 3800);
DBMS_OUTPUT.PUT_LINE('possibly raised PLSQL/SQL error: ' ||err_num||' - '||err_msg);
UTL_HTTP.END_RESPONSE(resp);
data := UTL_HTTP.GET_DETAILED_SQLERRM ;
IF data IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('possibly raised HTML error: ' ||data);
END IF;
END;
/
set serveroutput on
BEGIN
&clouduser..GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');
END;
/
set serveroutput off
drop procedure &clouduser..GET_PAGE;
2.5.Step 5: Configuring users and roles to
use DBMS_CLOUD
The following privileges are needed
for a user or role to use DBMS_CLOUD functionality. It’s recommended to grant
the necessary privileges through a role to make the management easier for
multiples users. In this example, we will use a local role named CLOUD_USER and
grant to a local user HR. you can modify the script according to your pluggable
database environment and execute it as privileged administrator, for example
SYS or SYSTEM within your pluggable database.
Create a script named create_role.sql and execute it on pluggable database.
$vi create_role.sql
set verify off
-- target sample role
define userrole='CLOUD_USER'
-- target sample user
define username='HR'
create role &userrole;
grant cloud_user to &username;
REM the following are minimal privileges
to use DBMS_CLOUD
REM - this script assumes core privileges
REM - CREATE SESSION
REM - Tablespace quote on the default tablespace for a user
REM for creation of external tables, e.g.
DBMS_CLOUD.CREATE_EXTERNAL_TABLE()
grant CREATE TABLE to &userrole;
REM for using COPY_DATA()
REM - Any log and bad file information is written into this directory
grant read, write on directory DATA_PUMP_DIR to &userrole;
REM
grant EXECUTE on dbms_cloud to &userrole;
Alternatively, you can grant the
privileges to an individual user. For example, you can use the following script
called grant_user.sql to grant privileges to HR user.
vi grant_user.sql
set verify off
-- target sample user
define username='SCOTT'
REM the following are minimal privileges
to use DBMS_CLOUD
REM - this script assumes core privileges
REM - CREATE SESSION
REM - Tablespace quote on the default tablespace for a user
REM for creation of external tables, e.g.
DBMS_CLOUD.CREATE_EXTERNAL_TABLE()
grant CREATE TABLE to &username;
REM for using COPY_DATA()
REM - Any log and bad file information is written into this directory
grant read, write on directory DATA_PUMP_DIR to &username;
REM
grant EXECUTE on dbms_cloud to &username;
2.6. Step 6: Configuring ACEs for a user
or role to use DBMS_CLOUD
DBMS_CLOUD is a package with invoker’s
right privilege. To provide all the functionality of DBMS_CLOUD to user or
role, you need to enable the appropriate Access Control Entries, similar to the
ones of DBMS_CLOUD.
Create the scripts called dbc_access_cloud_user.sql and dbc_access_hr.sql execute their in either CDB or the
PDB as SYS where you want to provide DBMS_CLOUD functionality to your user or
role. We will use a local role CLOUD_USER and grant the privileges to a local
user HR.
$vi dbc_access_cloud_user.sql
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
-- target sample role
define cloudrole=CLOUD_USER
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE
PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory
define sslwalletdir=<Set SSL
Wallet Directory>
--
-- UNCOMMENT AND SET THE PROXY
SETTINGS VARIABLES IF YOUR ENVIRONMENT NEEDS PROXYS
--
-- define proxy_uri=<your proxy URI address>
-- define proxy_host=<your proxy DNS name>
-- define proxy_low_port=<your_proxy_low_port>
-- define proxy_high_port=<your_proxy_high_port>
-- Create New ACL / ACE s
begin
-- Allow all hosts for HTTP/HTTP_PROXY
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 443,
upper_port => 443,
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => upper('&cloudrole'),
principal_type => xs_acl.ptype_db));
--
-- UNCOMMENT THE PROXY SETTINGS SECTION IF YOUR ENVIRONMENT NEEDS PROXYS
--
-- Allow Proxy for HTTP/HTTP_PROXY
-- dbms_network_acl_admin.append_host_ace(
-- host =>'&proxy_host',
-- lower_port => &proxy_low_port,
-- upper_port => &proxy_high_port,
-- ace => xs$ace_type(
-- privilege_list => xs$name_list('http', 'http_proxy'),
-- principal_name => upper('&cloudrole'),
-- principal_type => xs_acl.ptype_db));
--
-- END PROXY SECTION
--
-- Allow wallet access
dbms_network_acl_admin.append_wallet_ace(
wallet_path => 'file:&sslwalletdir',
ace => xs$ace_type(privilege_list =>
xs$name_list('use_client_certificates', 'use_passwords'),
principal_name => upper('&cloudrole'),
principal_type => xs_acl.ptype_db));
end;
/
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
$vi dbc_access_hr.sql
@$ORACLE_HOME/rdbms/admin/sqlsessstart.sql
-- target sample user
define clouduser=SCOTT
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE
PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory
define sslwalletdir=<Set SSL Wallet Directory>
-- Proxy definition
define proxy_uri=<your proxy URI address>
define proxy_host=<your proxy DNS name>
define proxy_low_port=<your_proxy_low_port>
define proxy_high_port=<your_proxy_high_port>
-- Create New ACL / ACE s
begin
-- Allow all hosts for HTTP/HTTP_PROXY
dbms_network_acl_admin.append_host_ace(
host =>'*',
lower_port => 443,
upper_port => 443,
ace => xs$ace_type(
privilege_list => xs$name_list('http', 'http_proxy'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
--
-- UNCOMMENT THE PROXY SETTINGS SECTION IF YOUR ENVIRONMENT NEEDS PROXYS
--
-- Allow Proxy for HTTP/HTTP_PROXY
-- dbms_network_acl_admin.append_host_ace(
-- host =>'&proxy_host',
-- lower_port => &proxy_low_port,
-- upper_port => &proxy_high_port,
-- ace => xs$ace_type(
-- privilege_list => xs$name_list('http', 'http_proxy'),
-- principal_name => upper('&clouduser'),
-- principal_type => xs_acl.ptype_db));
--
-- END PROXY SECTION
--
-- Allow wallet access
dbms_network_acl_admin.append_wallet_ace(
wallet_path => 'file:&sslwalletdir',
ace => xs$ace_type(privilege_list =>
xs$name_list('use_client_certificates', 'use_passwords'),
principal_name => upper('&clouduser'),
principal_type => xs_acl.ptype_db));
end;
/
@$ORACLE_HOME/rdbms/admin/sqlsessend.sql
2.7.Step 7: Validate the configuration
Assuming that you were setting up a
user named HR, create the following script named test_dbms_cloud.sql and execute it as SYS in the
pluggable database you were configuring.
$vi test_dbms_cloud.sql
-- user to trouble shoot
define clouduser=HR
-- CUSTOMER SPECIFIC SETUP, NEEDS TO BE
PROVIDED BY THE CUSTOMER
-- - SSL Wallet directory and password
define sslwalletdir=<Set SSL Wallet Directory>
define sslwalletpwd=<Set SSL Wallet password>
-- create and run this procedure as owner
of the ACLs, which is the future owner
-- of DBMS_CLOUD
CREATE OR REPLACE PROCEDURE &clouduser..GET_PAGE(url IN VARCHAR2) AS
request_context UTL_HTTP.REQUEST_CONTEXT_KEY;
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
data VARCHAR2(32767) default null;
err_num NUMBER default 0;
err_msg VARCHAR2(4000) default null;
BEGIN
-- Create a request context with its
wallet and cookie table
request_context := UTL_HTTP.CREATE_REQUEST_CONTEXT(
wallet_path => 'file:&sslwalletdir',
wallet_password => '&sslwalletpwd');
-- Make a HTTP request using the private
wallet and cookie
-- table in the request context
req := UTL_HTTP.BEGIN_REQUEST(
url => url,
request_context => request_context);
resp := UTL_HTTP.GET_RESPONSE(req);
DBMS_OUTPUT.PUT_LINE('valid response');
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 3800);
DBMS_OUTPUT.PUT_LINE('possibly raised PLSQL/SQL error: ' ||err_num||' -
'||err_msg);
UTL_HTTP.END_RESPONSE(resp);
data := UTL_HTTP.GET_DETAILED_SQLERRM ;
IF data IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('possibly raised HTML error: ' ||data);
END IF;
END;
/
set serveroutput on
BEGIN
&clouduser..GET_PAGE('https://objectstorage.eu-frankfurt-1.oraclecloud.com');
END;
/
set serveroutput off
drop procedure &clouduser..GET_PAGE;
If you are encountering problems with
DBMS_CLOUD with the user or role you just configured, you can if you user or
role does not have sufficient privileges or the certificate is valid.
Aucun commentaire:
Enregistrer un commentaire