I've been trying to get Oracle to call a REST API. While getting things set up and running we ran into an issue where our code generates an ORA-53203: security violation. In the process of isolating the issue we set up a procedure to test the connection and this, too, generates the same error.
We are using Oracle 12c and we've set up ACE/ACL entries for the host we're testing with for both 'connect' and 'resolve' permissions.
create or replace procedure showTitleTag ( i_url in varchar2 )
AS
l_httpreq UTL_HTTP.req;
l_httpresp UTL_HTTP.resp;
l_text varchar2(32767);
l_response CLOB;
l_title varchar2(32767);
BEGIN
l_httpreq := UTL_HTTP.begin_request(i_url);
l_httpresp := UTL_HTTP.get_response(l_httpreq);
BEGIN
LOOP
UTL_HTTP.read_text(l_httpresp, l_text, 32766);
l_response := l_response || l_text;
END LOOP;
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
UTL_HTTP.end_response(l_httpresp);
END;
l_title := REGEXP_REPLACE(l_response, '.*<title> ?(.+) ?</title>.*', '\1', 1, 1, 'in');
DBMS_OUTPUT.put_line(l_title);
EXCEPTION
WHEN OTHERS THEN
UTL_HTTP.end_response(l_httpresp);
RAISE;
END;
This code, should give us the contents of the web-page's title tag (we used "http://www.redhat.com" as our test URL). Instead we receive the following errors:
ORA-29273: HTTP request failed
ORA-53203: security violation
ORA-06512: at "APPS.SHOWTITLETAG", line 29
ORA-06512: at line 1
You need to make sure the related access control list (ACL) assigned and the right privilege has been granted to your target host.
If there's no problem with the first, then look
(select a.lower_port, a.upper_port from dba_network_acls a where a.host like '%i_url%')
whether you defined an interval for the ports of your URL, and
contains the port of the target host(s).
Related
I am trying to call an API from a procedure in oracle , for a demo purpose I tried calling a web page but its giving me error :
*Cause: The UTL_HTTP package failed to execute the HTTP request.
Set serveroutput on ;
DECLARE
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
value VARCHAR2(1024);
BEGIN
req := UTL_HTTP.BEGIN_REQUEST('http://www.nyquest.com');
resp := UTL_HTTP.GET_RESPONSE(req);
LOOP
UTL_HTTP.READ_LINE(resp, value, TRUE);
dbms_output.put_line(value);
END LOOP;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(resp);
END;
Please guide me in fixing this error .
Most likely you didnt created ACL's.
Your database needs it before it is going to accept connections from outside.
You can read about it here:
Oracle Access Control List
I run the write_test procedure, which works good.
begin
koll_data_pkg.write_test(p_customer_id=>247, p_addr=>'address', p_dir=>'\\SERVER01\Backup\Log\');
end;
But, when I change value of p_dir to another directory p_dir=>\SERVER12\Backup\Log\ it gives following error:
ORA-29283: invalid file operation
ORA-06512: by "SYS.UTL_FILE",
ORA-29283: invalid file operation
ORA-06512: by "DATA_PKG",
ORA-06512: by line
I have tried give permission using following commands, but still same error:
CREATE OR REPLACE DIRECTORY DEVO_INVREC_DIR AS '\\SERVER12\Backup\Log\';
GRANT READ, WRITE ON DIRECTORY DEVO_INVREC_DIR TO USER1;
GRANT READ, WRITE ON DIRECTORY DEVO_INVREC_DIR TO USER1;
GRANT EXECUTE ON UTL_FILE TO USER1;
Procedure:
procedure write_test(p_customer_id in koll_customer_party.customer_id%type,
p_addr in varchar,
p_dir in varchar,
p_filename in varchar2 default null)
is
lt_id id_tt;
lt_bolagsnamn bolagsnamn_tt;
l_file utl_file.file_type;
l_line varchar2(2048);
l_name varchar2(300):= 'DEVO_INVREC_DIR';
l_filename varchar2(100):= 'testfile.txt';
l_sql varchar2(512);
begin
select devo_id, bolagsnamn
bulk collect into lt_id, lt_bolagsnamn
from documents where customer_id=p_customer_id
if lt_id.count > 0 then
l_sql := 'create or replace directory ' || l_name || ' as ''' || p_dir || '''';
execute immediate l_sql;
if p_filename is not null then
l_filename := p_filename;
end if;
l_file := utl_file.fopen(l_name,l_filename,'w');
if utl_file.is_open(l_file) is not null then
for i in lt_id.first .. lt_devo_id.last loop
l_line:= lt_id(i) || ';' || replace(lt_bolagsnamn(i),';','');
utl_file.put_line(l_file, l_line);
end loop;
end if;
utl_file.fclose(l_file);
end if;
end;
Check out this forum response: https://community.oracle.com/thread/4145239?start=0&tstart=0
In summary, Oracle can't access the network shares in its default installed configuration because the Windows SYSTEM user can't access network shares by definition. You either have to reconfigure Oracle to run as a user other than SYSTEM, with permissions on the share, or allow SYSTEM to access network shares (a HUGE security risk). I was going to include a link describing how to change the user to be another service account, but they all seem to be broken or removed. It may depend on your exact version of Oracle and Windows, too, so you're best bet in the absence of other documentation would be to contact Oracle Support. There is no simple PL/SQL programming answer to your problem.
I am trying to write a simple function to verify whether a url is valid.
I started with an anonymous block that looks like;
DECLARE
httpuri HTTPURIType;
y CLOB;
x BLOB;
BEGIN
httpuri := HTTPURIType('http://google.com');
BEGIN
DBMS_OUTPUT.put_line(httpuri.getContentType());
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line('Bad Url');
END;
END;
/
This works fine, it outputs a "Bad Url" when the url is bad, and the mime type other wise.
Great let's write a function to encapsulate everything;
CREATE OR REPLACE FUNCTION CHECK_URL
(
URL_IN IN VARCHAR2
) RETURN VARCHAR2 AS
HTTPURI HTTPURIType;
OUT_STRING VARCHAR2(32767);
BEGIN
HTTPURI := HTTPURITYPE(URL_IN);
BEGIN
OUT_STRING := HTTPURI.GETCONTENTTYPE();
EXCEPTION
WHEN OTHERS
THEN
OUT_STRING := 'Error: Bad URL-' || URL_IN;
END;
RETURN OUT_STRING;
END CHECK_URL;
I call it with;
SELECT CHECK_URL('http://google.com') FROM DUAL;
or
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE(CHECK_URL('http://google.com'));
END;
/
This always returns "Error: Bad URL-" followed by the url entered. When I take out the exception handler, it gives the following error;
ORA-29273: HTTP request failed
ORA-06512: at "SYS.UTL_HTTP", line 1130
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at "SYS.HTTPURITYPE", line 123
ORA-06512: at "LMSADMIN.CHECK_URL", line 10
29273. 00000 - "HTTP request failed"
*Cause: The UTL_HTTP package failed to execute the HTTP request.
*Action: Use get_detailed_sqlerrm to check the detailed error message.
Fix the error and retry the HTTP request.
I have a minimal understanding of ACL lists. I am running both sets of code as the same user so I am not sure why I get differing results.
Edit: Database Version - 12c R2.
I am setting the timeout for 2 seconds but the code is running for a minute and is then going to when others instead of when UTL_HTTP.transer_timeout.
DECLARE
request UTL_HTTP.REQ;
response UTL_HTTP.RESP;
n NUMBER;
buff VARCHAR2 (4000);
clob_buff CLOB;
BEGIN
UTL_HTTP.SET_RESPONSE_ERROR_CHECK (FALSE);
UTL_HTTP.set_transfer_timeout (2);
request := UTL_HTTP.BEGIN_REQUEST ('www.google.com:81', 'GET');
UTL_HTTP.SET_HEADER (request, 'User-Agent', 'Mozilla/4.0');
response := UTL_HTTP.GET_RESPONSE (request);
DBMS_OUTPUT.PUT_LINE (
'HTTP response status code: ' || response.status_code);
EXCEPTION
WHEN UTL_HTTP.transfer_timeout
THEN
DBMS_OUTPUT.put_line ('Timeout');
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Exception in others :' || SQLERRM);
END;
Why isn't the timeout being caught?
You're getting a connection timeout rather than a transfer timeout. It's raised from the BEGIN_REQUEST, not the GET_RESPONSE; it isn't getting as far as transferring anything, it's just trying to open the connection to the remote host and port. If you had a connection and a GET or POST whose request/response exceeded 2 seconds then you would see UTL_HTTP.transfer_timeout. But you're seeing a transport layer problem, not an HTTP request problem.
You can catch the 'HTTP failure' part, but not specifically the TNS timeout as that is handled by UTL_HTTP:
DECLARE
...
http_failure exception;
pragma exception_init(http_failure, -29273);
BEGIN
...
EXCEPTION
WHEN UTL_HTTP.transfer_timeout
THEN
DBMS_OUTPUT.put_line ('Transfer timeout');
WHEN http_failure
THEN
DBMS_OUTPUT.put_line ('HTTP failure - timeout?');
RAISE;
END;
You could dig into the exception stack when you see that and pick out more specific errors, but it isn't clear what you want to do with the specific cause. Presumably you don't really want to catch it all, you're just debugging the exception to se why the timeout you set isn't working...
I'm not aware of any way to change the length of that timeout. Since it's from TNS it looks like it should be affected by the sqlnet.outbound_connect_timeout, but you set that in sqlnet.ora, and the server doesn't seem to be taking any notice of that in this scenario. It may be using the operating system defaults.
I have the following error message when I try to establish a HTTP request connection:
ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1029 ORA-12545: Connect failed because target host or object does not exist ORA-06512: at line 10 .
Line 10 is the following:
req := UTL_HTTP.BEGIN_REQUEST('oracle.com');
Here is my pl/sql block:
DECLARE
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
name_1 VARCHAR2(256);
value_1 VARCHAR2(1024);
v_msg VARCHAR2 (500);
BEGIN
req := UTL_HTTP.BEGIN_REQUEST('http://www.oracle.com');
UTL_HTTP.SET_HEADER(req, 'User-Agent', 'Mozilla/5.0');
UTL_HTTP.SET_FOLLOW_REDIRECT(req, 0);
resp := UTL_HTTP.GET_RESPONSE(req);
LOOP
Utl_Http.read_text (resp, v_msg);
DBMS_OUTPUT.put_line (v_msg);
END LOOP;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN Utl_Http.end_of_body
THEN
NULL;
END;
the code seems fine to me...
the reason of this error is outside the code you show:
The system this code is run on (the DB server) must be able to resolve the domain name - which has nothing to do with Oracle...
To solve this you need to setup DNS / hosts correctly on the machine / in the OS!