I am using Prisma 2 as interface with postgres db. I want to reset the db, however, when I try, I get the error:
✕ Resetting the database has failed with an error from the database:
✕ Error: Invalid `prisma.executeRaw()` invocation:
Raw query failed. Code: `42501`. Message: `db error: ERROR: must be owner of schema public`
The postgres role I created, aim, for the same named db has the following permissions:
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
aim | Create role, Create DB | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
I created a user by the same name in Ubuntu OS so I can connect to the db.
As per my understanding, the above error is because I do not have the permissions to alter or delete the db ``?
How would I go about fixing this. The commands from this link didn't delete the db aim either whether I was logged in as postges or aim role.
Related
I am trying to run Snowflake update using Liquibase as the following command which has fully qualified name of the server, database and the schema.
liquibase --username=myusername --password=mypassword --url="jdbc:snowflake://myserver-name-europe.azure.snowflakecomputing.com/?db=mydb&schema=public" --changelog-file=/samplechangelog.snowflake.sql update
But it just gives me error that I didn't specify the database which I did.
Also, the same command work with other Snowflake account? I just even copy and paste it from other project, it's just the name of the server URL and DB is the different.
Here is the error message:
Unexpected error running Liquibase: Cannot perform CREATE TABLE. This session does not have a current database. Call 'USE DATABASE', or use a qualified name. [Failed SQL: (90105) CREATE TABLE DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP_NTZ, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID))]
I suggest setting up a default role for user "username":
ALTER USER myusername SET DEFAULT_ROLE = my_default_role;
If user does not have default warehouse assigned then:
ALTER USER myusername SET DEFAULT_WAHREOUSE = my_warehouse_name;
It is also possible to set dabatabase/schema/warehouse/... in db.properties file. Related: Specifying Properties in a Connection Profile
This error is usually due to insufficient permissions - if the user cannot 'see' the database, liquibase silently sets it to null and then fails with this error. The best method of troubleshooting this is to connect via Snowflake web GUI with the same credentials (without setting any role or warehouse), then try running 'use database ...'.
The solution is to grant enough permissions to the user - either directly or via a role (but then the role name needs to be passed on in the jdbc connection string as well).
Yes, the issue was in the permissions for the current user that I am trying to use to connect to the Snowflake, here what I did:
ALTER USER myuser SET DEFAULT_ROLE=SYSADMIN
This lead to another error as there is no active warehouse, so I set the whorehouse in the connection string of the JDBC driver as the following:
liquibase --username=myusername --password=mypassword --url="jdbc:snowflake://myserver-name-europe.azure.snowflakecomputing.com/?&warehouse=COMPUTE_WH&db=mydb&schema=public"--changelog-file=/samplechangelog.snowflake.sql update
So, I can send any values in the connection string for the JDBC as the following:
jdbc:snowflake://myorganization-myaccount.snowflakecomputing.com/?user=peter&warehouse=mywh&db=mydb&schema=public
Here is the page for more info about JDBC driver connection string:
JDBC connection string to Snowflake
I have restored a SQL Server 2019 database from a .BAK file to a Google Cloud SQL instance.
I can connect to the instance using Visual Studio SQL Connection. I issue the following command to check the database owner, which should be: mydb_adm
USE master;
SELECT suser_sname(owner_sid) AS 'DB Owner' FROM sys.databases WHERE name = 'mydb';
DB Owner
--------
sqlserver
The above is expected, as the restore was done while using the sqlserver account which is the default user created when the SQL instance is provisioned by Google Cloud (according to the docs).
So, I need to change the DB owner; I execute the following command:
USE mydb
EXEC sp_changedbowner 'mydb_adm'
The system displays the following error message:
Msg 15151, Level 16, State 1, Line 1
Cannot find the principal 'mydb_adm', because it does not exist or you do not have permission.
The same message is displayed for:
ALTER AUTHORIZATION ON DATABASE::mydb TO mydb_adm;
However, the "mydb_adm" principal DOES exist, i.e.:
SELECT name, sid FROM sys.server_principals WHERE name = 'mydb_adm';
name sid
---- ---
mydb_adm 0xD81398C7DB0D724BB2738A2EC59BB554
.. so it must be a permission problem with the sqlserver account. When I query the DB, it appears the "sqlserver" user does NOT have ALTER permissions, i.e.:
UserName Permission Type Permission State
-------- --------------- ----------------
sqlserver ALTER DENY
... So how can I change the database owner or issue any ALTER commands using the "sqlserver" account? (There seems to be no way to grant the ALTER permission to the sqlserver user).
Any help / advice would be appreciated.
Thank-you to #DanGuzman for providing a "work-around", i.e.: while connected to the SQL instance using the "sqlserver" user, the following commands were used:
USE mydb;
CREATE USER mydb_adm;
ALTER ROLE db_owner ADD member mydb_adm;
After some additional digging, I also found the following in the Google Cloud docs at https://cloud.google.com/sql/docs/sqlserver/users, which states:
Cloud SQL for SQL Server is a managed service, so it restricts access
to certain system stored procedures and tables that require advanced
privileges. In Cloud SQL, you cannot create or have access to users
with superuser permissions.
Note: The sysadmin role is not supported. Therefore, you cannot run
system stored procedures that require the sysadmin role. As one of
the many examples, you cannot run the sp_OADestroy stored procedure
because it requires the sysadmin role.
As well as the following from the SQL Server docs at https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql?view=sql-server-ver15#remarks, which state:
Requirements for the person executing the ALTER AUTHORIZATION
statement: If you are not a member of the sysadmin fixed server role,
you must have at least TAKE OWNERSHIP permission on the database, and
must have IMPERSONATE permission on the new owner login.
hence, commands such as EXEC sp_changedbowner ... or ALTER AUTHORIZATION ON DATABASE:: ... will raise the error (Msg 15151, ... you do not have permission.)
Hope that helps anyone else that may run into this type of issue.
I am a sysadmin on an SQL Server instance. I have created and added an AD group to manage security to the server logins and have also mapped it to a database with db_datareader and db_datawriter roles...
If I navigate to the database and look at the permissions for the added group, I can see the explicit but NOT the effective permissions, I get the message "cannot execute as the server principal because the principal does not exist this type of principal cannot be impersonated, or you do not have permission"
If I do the same for the next user in the list I can see both explicit and effective permissions, etc etc, until I hit another user and get the same message.
I have tried to add a single AD user to DB logins and I can see both explicit and effective.
I have tried to add a different AD group on a different database and I get the error
This is because to check the effective permissions SSMS tries to execute the code like this:
execute as login = '...';
select *
from sys.fn_my_permissions(null, 'server');
here '...' is the login for whom's permissions you are looking for.
But the login that is a Windows Group cannot be impersonated,
so the first statement execute as login = 'MyADGroup'; gives you an error
"cannot execute as the server principal because the principal does not exist this type of principal cannot be impersonated, or you do not have permission".
To check the effective permissions of the group you can execute this code by yourself with some member of this Group in execute as login
And here is BOL article EXECUTE AS (Transact-SQL) that says:
{ EXEC | EXECUTE } AS [;]
::= { LOGIN | USER } = 'name'
[ WITH { NO REVERT | COOKIE INTO #varbinary_variable } ] | CALLER
...
name must be a singleton account, and cannot be a group,
role, certificate, key, or built-in account, such as NT
AUTHORITY\LocalService, NT AUTHORITY\NetworkService, or NT
AUTHORITY\LocalSystem.
How can grant all the rights and privileges of the db_owner fixed database role to an application role?
Short Version
The command:
GRANT CONTROL ON [DatabaseName] TO [ApplicationRoleName];
would be what I want, but it fails with:
Msg 15151, Level 16, State 1, Line 23
Cannot find the object 'DatabaseName', because it does not exist or you do not have permission.
Research Effort
I'm investigating using SQL Server Application Roles.
it's like a user (in that it has a username and password)
and it's like a role
Once connected to the server, your application runs a stored procedure to "login" itself as the application:
EXECUTE sp_SetAppRole #rolename = 'Contoso.exe', #password =
'Tm8gaSBkaWRuJ3QganVzdCBiYXNlNjQgZW5jb2RlIGEgcGFzc3dvcmQuIEl0J3Mgb25seSBhbiBleGFtcGxlIQ==';
Permissions of db_owner
Normally the application logs in as a user who is a member of the db_owner fixed role. The db_owner role has permission:
to everything
on every table
every view
every stored procedure, function
for all existing objects
and all objects that will exist in the future
And while:
you can place a user into a database role
you can place a user into an application role
You cannot place an application role into a database role
So, the question then: how to grant my application role all permissions (i.e. to do everything)?
Permissions for a role
So, now is the time to grant permissions to the role. Following this page's suggestions:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO [Contoso.exe];
That's interesting and all, but it doesn't grant all privileges - it only grants SELECT, INSERT, UPDATE, and DELETE. I want to grant everything - especially when I don't know what all the privileges are (or could be).
I blindly try:
GRANT ALL ON Users to [Contoso.exe];
and the following appeared in the "Messages" tab:
The ALL permission is deprecated and maintained only for compatibility. It DOES NOT imply ALL permissions defined on the entity.
Ok, so granting ALL doesn't grant ALL. That's...terrifying.
So I'm back to:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO [Contoso.exe];
Except that doesn't grant everything. For example, I happen to know there's an ability to then go on to grant privileges to others (a privilege that db_owner has). So I have to change my statement to:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO [Contoso.exe] WITH GRANT OPTION;
Ok, so that's closer, but it only applies to one table.
I need something that applies to all tables:
EXECUTE sp_msForEachTable 'GRANT SELECT, INSERT, UPDATE, DELETE ON ? TO [Contoso.exe] WITH GRANT OPTION;';
Although, it turns out I missed some privileges:
SELECT ✔️
INSERT ✔️
UPDATE ✔️
DELETE ✔️
REFERENCES ❌
ALTER ❌
Sure, I can update my script:
EXECUTE sp_msForEachTable 'GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES, ALTER ON ? TO [Contoso.exe] WITH GRANT OPTION;';
But, rather than this cat-and-mouse guessing game: I want to grant ALL permissions.
ALL is nearly all
In the warning above, SQL Server notes that ALL doesn't grant all. But they do document what all does grant:
| Permission | Table | View | SP | Scalar UDF | Table UDF |
|------------|-------|------|----|------------|-----------|
| SELECT | ✔️ | ✔️ | | | ✔️ |
| INSERT | ✔️ | ✔️ | | | ✔️ |
| UPDATE | ✔️ | ✔️ | | | ✔️ |
| DELETE | ✔️ | ✔️ | | | ✔️ |
| REFERENCES | ✔️ | ✔️ | | ✔️ | ✔️ |
| EXECUTE | | | ✔️ | ✔️ | |
| ALTER | ❌ | ❌ | ❌ | ❌ | ❌ |
CONTROL all permissions
Turns out that they were all of them deceived. For another permissions was created. One permission to rule them all:
CONTROL
Confers ownership-like capabilities on the grantee. The grantee effectively has all defined permissions on the securable. A principal that has been granted CONTROL can also grant permissions on the securable. Because the SQL Server security model is hierarchical, CONTROL at a particular scope implicitly includes CONTROL on all the securables under that scope. For example, CONTROL on a database implies all permissions on the database, all permissions on all assemblies in the database, all permissions on all schemas in the database, and all permissions on objects within all schemas within the database.
They go on to enumerate the permissions that are implied when you have CONTROL:
ALTER
CONTROL
DELETE
EXECUTE
INSERT
RECEIVE
REFERENCES
CONTROL
TAKE OWNERSHIP
UPDATE
VIEW CHANGE TRACKING
VIEW DEFINITION
That's much better. Rather than having to know all the permissions, I just grant one. And rather than knowing which permissions are applicable to what kinds of objects, I grant just one. And because of the line:
A principal that has been granted CONTROL can also grant permissions on the securable.
I don't have to GRANT WITH GRANT:
-- when you have CONTROL you also get WITH GRANT for free
EXECUTE sp_msForEachTable 'GRANT CONTROL ON ? TO [Contoso.exe];';
To all objects
My issue is that I need to give CONTROL permission to every object in the database. And any time any new object is added, I have to be sure to go back and add it to the application role.
What I need is the thing hinted to by Microsoft:
For example, CONTROL on a database implies all permissions on the database, all permissions on all assemblies in the database, all permissions on all schemas in the database, and all permissions on objects within all schemas within the database.
To restate, if you grant CONTROL on a database, then you will have all permissions:
on the database
all objects
all assemblies in the database
all schemas
That is what I want. I want to GRANT CONTROL permission on the Grobber database to the [Contoso.exe] application role:
GRANT CONTROL ON Grobber TO [Contoso.exe];
Msg 15151, Level 16, State 1, Line 23
Cannot find the object 'Grobber ', because it does not exist or you do not have permission.
I may have nearly solved my problem, only to be stopped at the 1 yard line.
Or, I may be nowhere near. So I ask on S.O.:
How to grant db_owner permissions to another role?
Edit: Warning: Don't use application roles - it breaks everything
When your client logs into an app role, that identity is a persistent property of that connection. And with connection pooling on (as is the preferred and default option in ADO.net, and ADO, and ODBC) that connection stays open for a long time - even after you close the connection.
When your application (i.e. web-server) tries to open a new connection, it grabs one from the connection pool. The first thing that the SqlConnection does is try to reset the state of the connection back to default (using sp_reset_connection).
One of the things that sp_reset_connection tries to do is undo the fact that you are app role user. That is not allowed (because the server doesn't know who you were before). So by using application roles, you will suddenly get errors when you attempt to connect to the server.
The only way to "fix" it is to disable connection pooling.
Which is something that you don't want to do.
So the solution is to not use application roles in a production setting.
"You cannot place an application role into a database role" appears to be the part that's not correct. An (application) role can be added as a member of another role:
EXEC sp_addrolemember 'db_owner', 'ApplicationRoleName';
(From 2012 onwards, this procedure has been deprecated in favor of the new ALTER ROLE .. ADD MEMBER syntax.)
To GRANT CONTROL on an entire database to a role, the following will do:
USE [DatabaseName];
GRANT CONTROL ON DATABASE::[DatabaseName] TO [ApplicationRoleName];
The USE is necessary to bring the role in scope; the DATABASE:: scope qualifier is always necessary when referencing databases.
Having said all that, an application role is probably not a good candidate to grant the broadest of permissions to. The password for it is passed in plaintext unless care is taken to encrypt the connection itself, monitoring and auditing may overlook it, and it's easy to forget to revert when the permissions are no longer needed. That last part is extra insidious because an unreverted app role activation will persist across pooled connections, leaving a connection "stuck" in admin mode. Alternatives include opening a separate connection with new credentials for arbitrary actions and using stored procedures with EXECUTE AS for permissions that can't be GRANTed effectively.
One of the things that sp_reset_connection tries to do is undo the fact that you are app role user. That is not allowed (because the server doesn't know who you were before).
...
The only way to "fix" it is to disable connection pooling.
Undoing the app role can't be done automatically by sp_reset_connection, but it can be done (starting in SQL Server 2005). It just needs to be done manually via sp_unsetapprole. This requires instructing sp_setapprole to generate a cookie (VARBINARY value), capturing it when you execute that system proc, and storing it somewhere (in SQL Server via CONTEXT_INFO or the newer SESSION_CONTEXT, or in the app layer). Then, you just need to pass that value back to sp_unsetapprole before closing the SqlConnection (i.e. returning that connection to the pool).
It's theoretically possible that using EXECUTE AS to switch security contexts would be something that sp_reset_connection could undo since it only requires executing REVERT in T-SQL (no cookie value required), and does not error if there was no context switch to be reverted (REVERT only throws an error if called while the active database is different from when EXECUTE AS was executed). However, I have no time to test this (and it's not a recommended practice anyway).
Normally the application logs in as a user who is a member of the db_owner fixed role.
Now that is certainly not ideal (especially if the login that owns the database has any admin privileges). Yes, it certainly does make some tasks easier as you are effectively disabling all security so that you never get a permissions error, but this approach is highly unsecure, even if you did add the extra step of the password required to set the app role.
The preferred approach (that is very granular and very secure) is to use Module Signing. By signing your modules (stored procedures, scalar functions, multi-statement TVFs, and triggers), you can give them (the modules) any permissions necessary to perform the code that the encapsulate, with no fear of anyone taking those permissions and doing something unintended with them. In this approach, you are granting permissions to the code, not to users (i.e. people / application logins). I have more details as to why you want to move away from app roles and EXECUTE AS, and switch to module signing: PLEASE, Please, please Stop Using Impersonation, TRUSTWORTHY, and Cross-DB Ownership Chaining. For specific examples, please see:
Safely and Easily Use High-Level Permissions Without Granting Them to Anyone: Database-level
Safely and Easily Use High-Level Permissions Without Granting Them to Anyone: Server-level
I need to convert a database link that I have in Oracle from a normal public database link to a public shared database link.
I ran the following as my user with DBA privileges to make the link shared:
DROP PUBLIC DATABASE LINK "MYDBLINK";
CREATE SHARED PUBLIC DATABASE LINK "MYDBLINK"
AUTHENTICATED BY SOME_USER
IDENTIFIED BY thepassword
USING 'OTHERDB';
I used the same username and password as the database link was already using.
When I query across the database link with my user that has DBA privileges, it works fine. But when I use a non-DBA privileged user, and I inspect the database link, it shows that the user name for the database link is null, and if I try to query across the link, I get:
ORA-01017: invalid username/password; logon denied
Any ideas why the link would behave differently for non-DBA users?
Authentication to the remote database is done by using the credential defined on AUTHENTICATED BY clause. Once the connection is established, operation on the remote database proceeds with the privileges of the user defined on CONNECT TO clause or CURRENT USER, no the AUTHENTICATED BY schema.
In your case, you have not defined CONNECT TO schema hence it is using the current user in the local database to operate on the remote database. If your currently logged in user on the local database doesn't exist on the remote server then you get this error.
Here is a demo.
On a Local Database(AS SYSDBA)
SQL> CREATE SHARED PUBLIC DATABASE LINK link2remotedb
AUTHENTICATED BY userA_uat IDENTIFIED BY userA_uat
USING 'ORCLUAT';
Database link created.
Then I connected by a user which exists on my local database but not on the remote database.
SQL> conn jay/jay
Connected.
SQL> select * from address#link2remotedb;
select * from address#link2remotedb
*
ERROR at line 1:
ORA-01017: invalid username/password; logon denied
ORA-02063: preceding line from LINK2REMOTEDB
The error has occurred because the SELECT operation used the current user which is JAY to select from the ADDRESS table on the remote database. JAY user doesn't exist on the remote database.
So, what next?
Define the user in CONNECT TO clause.
SQL> CREATE SHARED PUBLIC DATABASE LINK link2remotedb
CONNECT TO userA_uat IDENTIFIED BY userA_uat
AUTHENTICATED BY userA_uat IDENTIFIED BY userA_uat
USING 'ORCLUAT';
Database link created.
SQL> conn jay/jay
Connected.
SQL> select * from address#link2remotedb;
Documentation
Using Shared Database Links