What Oracle privileges do I need to use DBMS_METADATA.GET_DDL? - oracle

(Excuse any ignorance of mine here - I'm not a seasoned Oracle user.)
I'm attempting to use the DBMS_METADATA.GET_DDL function (in conjunction with ALL_OBJECTS or some such) to get the DDL for all of the tables in a particular schema. When I do this (either for all objects or for a single specific object) I get an ORA-31603 error ("object "FOO" of type TABLE not found in schema "SCHEMA").
I assume this means that the user I'm logged in with doesn't have whatever privilege is necessary to read the metadata needed for GET_DDL. What privilege is this that's needed? Is there a way when logged in to confirm that the current user does/does not have this privilege?
thanks!
Lee

Read this document, but basically, you need SELECT_CATALOG_ROLE
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_metada.htm#i1016867

Related

DB2- how to prevent user viewing view DDL

i'm having this situation whereby user are using Dbeaver to access to DB2. There is some views created. At the moment user have the ability to use the Dbeaver to see the view DDL (back end code).
Question : how/is there any way to prevent the user see the view DDL?
much appreciate you advice
Look at the Db2 Obfuscation facility.
CALL DBMS_DDL.CREATE_WRAPPED ('CREATE OR REPLACE VIEW TEST_OBFUSCATED AS SELECT TABNAME FROM SYSCAT.TABLES WHERE TABSCHEMA LIKE ''SYS%''');
SELECT TEXT
FROM SYSCAT.VIEWS
WHERE VIEWSCHEMA = CURRENT SCHEMA AND VIEWNAME = 'TEST_OBFUSCATED';
TEXT
CREATE OR REPLACE VIEW TEST_OBFUSCATED WRAPPED SQL11014 long_meaningless_string
You may use this view as any other one in the same way, but its text is not visible for everyone.
Moreover, you can use this "strange" obfuscated statement to create the view from scratch. There is a scalar function which helps you to get this obfuscated statement without creation it first.
VALUES DBMS_DDL.WRAP ('CREATE OR REPLACE VIEW TEST_OBFUSCATED AS SELECT TABNAME FROM SYSCAT.TABLES WHERE TABSCHEMA LIKE ''SYS%''')
If someone still needs to view the real view text, you may use Row and column access control (RCAC) on the SYSIBM.SYSVIEWS table.
If you want your users to be able to select from a view, they must be able to obtain the definition of that view.
You can wrap the query against the view in a set-returning user-defined function, which has all privileges of its creator, presumably a DBA, and grant other users only the EXECUTE privilege on that function. You will then be able to revoke from your users the privileges to read system catalog tables that you don't want them to read.
Details in the manual.

How to use synonym of a DBlink in Oracle?

I have created a synonym for a dblink.
create synonym dblink2 for dblink1
But when I query anything using the synonym instead of the dblink, I'm getting connection description for remote database not found error.
SELECT * FROM DUAL#DBLINK2
How do I query using the synonym?Edit: I know that it'll work if I create a view of the table using dblink. But my requirement is the above question.
Unfortunately creation of synonyms for dblinks is not supported. If you read the documentation on synonyms, you will find that the permitted objects for synonyms are only:
Use the CREATE SYNONYM statement to create a synonym, which is an
alternative name for a table, view, sequence, procedure, stored
function, package, materialized view, Java class schema object,
user-defined object type, or another synonym.
The reason why your second query fails is that the synomym you have created is not functioning correctly. It is not being validated properly at creation time, and you can create any sort of incorrect synonyms like that. To verify, just test the following statement:
create synonym dblink3 for no_object_with_this_name;
You will still get a response like this:
*Synonym DBLINK3 created.*
But of course nothing will work via this synonym.
I don't see the point in creating a synonym for the dblink itself. Ideally you create the synonym for the remote table using the dblink.
CREATE DATABASE LINK my_db_link CONNECT TO user IDENTIFIED BY passwd USING 'alias';
CREATE SYNONYM my_table FOR remote_table#my_db_link;
Now, you could query the remote table using the synonym:
SELECT * FROM my_table;
I'm trying to think of the business issue that gets solved by putting a synonym on a db_link, and the only thing I can think of is that you need to deploy constant code that will be selecting from some_Table#some_dblink, and although the table names are constant different users may be looking across different db_links. Or you just want to be able to swap which db_link you are operating across with a simple synonym repoint.
Here's the problem: it can't be done that way. db_link synonyms are not allowed.
Your only solution is to have the code instead reference the tables by synonyms, and set private synonyms to point across the correct db_link. That way your code continues to "Select from REMOTE_TABLE1" and you just can flip which DB_LINK you are getting that remote table from.
Is it a pain to have to set/reset 100+ private synonyms? Yep. But if it is something you need to do often then bundle up a procedure to do it for you where you pass in the db_link name and it cycles through and resets the synonyms for you.
While I understand that this question is 3+ years old, someone might be able to benefit from a different answer in the future.
Let's imagine that I have 4 databases, 2 for production and 2 for dev / testing.
Prod DBs: PRDAPP1DB1 and PRDAPP2DB1
Dev DBs: DEVAPP1DB1 and DEVAPP2DB1
The "APP2" databases are running procedures to extract and import data from the APP1 databases. In these procedures, there are various select statements, such as:
declare
iCount INTEGER;
begin
insert into tbl_impdata1
select sysdate, col1, col2, substr(col3,1,10), substr(col3,15,3)
from tbl1#dblink2; -- Where dblink2 points to DEVAPP1DB1
...
<more statements here>
...
EXCEPTION
<exception handling code here>
end;
Now that is okay for development but the dblink2 constantly needs to be changed to dblink1 when deploying the updated procedure to production.
As it was pointed out, synonyms cannot be used for this purpose.
But instead, create the db links with the same name, different connection string.
E.g. on production:
CREATE DATABASE LINK "MyDBLINK" USING 'PRDAPP1DB1';
And on dev:
CREATE DATABASE LINK "MyDBLINK" USING 'DEVAPP1DB1';
And then in the procedures, change all "#dblink1" and "#dblink2" to "#mydblink" and it all should be transparent from there.
If you are trying to have the DB link accessible for multiple schemas (users) the answer is to create a public db link
example:
CREATE PUBLIC DATABASE LINK dblink1 CONNECT TO user IDENTIFIED BY password USING 'tnsalias';
After that any schema can issue a:
SELECT * FROM TABLE#dblink1

Is it possible to see a sequence in all_sequences without having the SELECT right on the sequence?

I need to retrieve the list of available sequences of a certain database schema in an Oracle 10g database (10.2.0.3).
With the schema owner, I can simply do something like the following to achieve this:
SELECT sequence_name FROM all_sequences WHERE sequence_owner = 'ABCDEF';
However, If I use a user which has a custom "read-only" role assigned, that user does not get any rows when executing that query.
I've played around a bit and found out that granting the SELECT option on the sequences to the read-only role makes those sequences appear in the all_sequences view when connected with the read-only user.
However this means that the read-only user is able to do
SELECT my_sequence.NEXTVAL FROM DUAL;
which is a no-go for our situation (after all, the read-only user shall not be able to modify anything, not even sequences).
Is there another way for retrieving the sequences which does not allow selecting NEXTVAL?
[Edit:]
If I do
SELECT DISTINCT sequence_owner FROM all_sequences;
I get the following list:
SEQUENCE_OWNER
------------------------------
MDSYS
DMSYS
OLAPSYS
XDB
SYS
5 rows selected
After using the system user to do
GRANT SELECT ANY DICTIONARY TO MY_USER;
the result stays the same (revoke does not change anything either).
Granting the SELECT_CATALOG_ROLE instead does not work either.
Granting SELECT on at least one of the sequences however changes the result to include my own schema owner.
You can try to grant SELECT ANY DICTIONARY privilege, but it's very bad for the security reasons, so, I guess, your DBA will deny it.
Good decision is to create table function publishes required data. By default this function will work with AUTHID DEFINER rights, so you should just grant it to read-only user and it would receive sequences info without any chance to change them.
The best solution I can come up with is to grant the user SELECT ANY DICTIONARY. This will give them access to DBA_SEQUENCES (as well as all of the other DBA_ views) without needing permissions on the objects.

OracleDatareader seems to execute an update statement

I am using oracle client 11.2.0
Dll version 4.112.3.0
We have a page in our application where people can give a sql statement and retreive results. basically do an oracle command.executereader
Recently one of my team members gave an update statement as a test and it actually performed an update on a record!!!!
Anyone who has encountered this?
Regards
Sid.
It is a normal (albeit a bit unsettling) behavior. ExecuteReader is expected to execute the sql command provided as CommandText and build a DbDataReader that you use to loop over the results.
If the command doesn't return any row to read is not something that the reader should prevent in any case. And so it is not expected that it checks if your command is really a SELECT statement.
Think for example if you pass a stored procedure name or if you have multiple sql batch to execute. (INSERT followed by a SELECT)
I think that the biggest problem here is the fact that you allow an arbitrary sql command typed by your users to reach the database engine. A very big hole in security. You should, at least, execute some analysis on the query text before submitting the code to the database engine.
I agree with Steve. Your reader will execute any command, and might get a bit confused if it's not a select and doesn't return a result set.
To prevent people from modifying anything, create a new user, grant select only (no update, no delete, no insert) on your tables to that user (grant select on tablename to seconduser). Then, log in as seconduser, and, create synonyms for your tables (create synonym tablename for realowner.tablename). Have your application use the seconduser when connecting to the DB. This should prevent people from "hacking" your site. If you want to be of the safe side, grant no permissions but create session to the second user to prevent him from creating tables, dropping your views and similar stuff (I'd guess your executereader won't allow DDL, but test it to make sure).

Oracle Syntax for Creating Database Link Owned by Another User

The typical syntax for creating a db link is as follows:
create database link remote_db_link
connect to remote_user
identified by remote_password
using 'remote_db'
But I'd like my DB link owned by another account after it's created. Is there a way to do this?
The following does NOT work:
create database link anotheruser.remote_db_link
connect to remote_user
identified by remote_password
using 'remote_db'
Sathya is correct, in that the CREATE DATABASE LINK syntax does not allow creating a database link in another schema. HOWEVER...
WORKAROUND
It IS possible to create a database link in another user's schema, as long as anotheruser has CREATE DATABASE LINK privilege, and the user you are connected as has CREATE ANY PROCEDURE privilege.
Here's the workaround I use:
create procedure anotheruser."tmp_doit_200906121431"
is
begin
execute immediate '
create database link remote_db_link
connect to remote_user
identified by remote_password
using ''remote_db'' ';
end;
/
begin
anotheruser."tmp_doit_200906121431";
end;
/
drop procedure anotheruser."tmp_doit_200906121431"
/
Let's unwind that. First, I create a procedure in the anotherusers's schema; this procedure contains the CREATE DATABASE LINK statement that I want to run.
When the procedure is executed, it runs as the owner of the procedure, such that the CREATE DATABASE LINK statement is executed by anotheruser.
The name of the procedure is not important, except that I need to make sure that it doesn't conflict with any existing object name. I use lowercase letters (enclosing the procedure name in double quotes), using "tmp" to mark this object as "temporary", and using the current yyyymmddhh24miss as the part of the procedure name. (I usually run a query of DBA_OBJECTS to check that a matching object_name does not exist.)
For a "one-off" type admin function, this is a viable workaround. I prefer this to the other alternative: saving the anotheruser's password, changing the password, connecting as the user, and resetting anotheruser's password back to the saved.)
Restrictions on DBLinks - You cannot create a database link in another user's schema, and you cannot qualify dblink with the name of a schema.
AS a sys user you can view all db links in SYS.DBA_DB_LINKS view.
That view use link$ and user$ table.
You can create new dblink as usually and it show at link$ table. Then change owner (use id from user$). commit. Done.

Resources