How to secure SharePoint Shared SSRS Datasources - sql-server

I have a large reporting SharePoint site that contains about a dozen different shared data source connections, each one pointing at a different SQL server that is being utilized by the SSRS reports hosted on the site. Each data source has a cached account that is used to retrieve the data when a report runs so that report readers do not have to have read access to all of our SQL databases.
When someone with report building privileges creates a report, they are able to select one of the shared data sources hosted on the website, but then have to pass an authentication popup before they can actually write a query against the database:
The strategy currently in use is that our authors do have read access to the SQL database and use that authentication (Use the current Windows user) to create the report and then when they save the report, readers utilize the account stored in the shared data source. We then manage access to the data in the report through SharePoint security by only allowing people who should see that data to have access to the report.
This seems all very standard to me...however
I am able to query any database that any of the shared data sources have access to, regardless of my own permissions with a bit of rdl definition manipulation by following these steps:
1) Current account needs access to report builder and AD access to at least one SQL datasource (to make things easier)
2) Add a shared data source to the report that I have access to
3) Add a dataset with a query that follows this format SELECT '' as Field1 FROM DBNAME
4) Add a table to the report that simply displays Field1 from the query
5) Add one of the shared data sources that I should have no access to (there is no stopping me from adding the shared connection to the report, I simply am unable to use report builder to create a dataset using that data source)
6) Save report on the SharePoint site and then download a copy to local computer
7) Open rdl definition. Replace the data source for the SQL query with the name of the "unauthorized" data source (can delete original data source). Replace the SQL query with one that queries the database for a list of table names (SELECT name as Field1 FROM sys.Tables)
8) Upload report definition back to SharePoint and run report
The report now uses the cached account and I've bypassed the nice authorization window that using report builder would have provided. By using sys queries, I can find the databases, tables, columns and eventually the data without having to know anything about the database. I could slow this method done by preventing access to the master database so that a list of databases can't be retrieved, but that's minor and not a complete solution.
Options:
- Could enforce security at the database level, however I don't want report readers to have permission against any of my source databases. While each report could be fed from a view and then separately controlled to prevent access to anything more than what the report shows, this would be uncontrollable
- Force every report to use an embedded connection and not a shared connection. This would be hard to manage in the future when moving servers or when we need to know what reports are utilizing a specific connection (dependent items are available in the data source drop down menu)
I feel like I'm missing something obvious here as this seems to totally defeat the purpose of hosted, shared data sources.

The advantages of Shared Data Sources are administrative, in that they reduce the overhead in making changes to data source connection details such as passwords and server names. As you pointed out, using Shared Data Sources also allows you to easily identify dependent reports.
However Shared Data Sources are not a mechanism for securing data sources such as databases. Security really needs to be addressed at the database level to properly ensure only authorized people have access. If the credentials are stored in the report data source, then anyone able to access that data source or refernce it in a report is going to be able to execute queries on the connection.
I think the issue is in this step:
5) Add one of the shared data sources that I should have no access to
(there is no stopping me from adding the shared connection to the
report, I simply am unable to use report builder to create a dataset
using that data source)
There should be some way to prevent the report designers seeing shared data sources that they do not have permissions on. You might need to set individual permissions for each item, or put them in different locations to allow them to be secured with the correct permissions. I'm not a Sharepoint expert though so this is just a suggestion.

Related

Crystal Reports can access tables, but not views

I've written a Crystal report that primarily works from a temporarily MDB file that is created on the fly in an Application (which I do not have access to source code for).
I need additional data, so I linked to a secondary MSSQL database where I store more information.
I was able to add tables from this SQL database to my report, and link to them with no trouble. But when I try to include views in this same SQL database in this report, I get a "Logon Error".
My first thought was that is is a permission issue, but I haven't set permissions for specific tables and views in this database, only permissions to the entire database.
Frustratingly, I don't see any errors in the SQL logs for the database.
Does anyone have ideas on what I can check to get this fixed?
Just To Clarify: I can see these views in the Crystal Report, and I can add them, add fields to the report, and create links. I can even Browse Data in fields within the view in Crystal. It's only when running these reports from the 3rd party application that I get an error.
Is SQL Server set to use NT Authentication? If so, the 3rd-party application is probably running under a user context that doesn't have permissions.

How do I change permissions on data sources?

I'm migrating an SSRS installation from SQL Server 2005 to 2016. Last time I did this was I migrated it from SQL Server 2000 to 2005 and this is still the same ReportingServices databases.
I restored it on another server, set up a SSRS instance and going through all the active reports to check them.
This time I'm also deleting all data sources that are in folders or used by single reports and pointing reports to shared data sources.
My problem is that most of the time this is run by developers who develop, upload and set permissions for folders and reports and I've found that I cannot delete some data sources. I've pointed the reports to shared data sources but I want to get rid of these unused data sources.
I've added myself to the top level and lower level folder content manager role but still cannot do it
My worry is that developers will overwrite these reports with changes and upload them with a local data source or create new data sources again. In a DR situation I don't want change dozens of data sources.
If you can add yourself as an Administrator role, you should be able to do whatever you want. Failing that, I can guarantee this will work:
You can go to your SSRS config tool to confirm the ReportServer Database location but it is probably located on your SQL Server in the ReportServer$INSTANCENAME database.
In there is a dbo.DataSource table which contains all of the Data Sources. You can look for the name of the Data Source you want to remove and drop that row from the table. Be careful that this also contains all Paginated embedded Data Sources so make sure you have the right one identified before you drop it.

Limit Oracle object set in SQL Server Migration Assistant

I have a large Oracle source database with many objects and wish to migrate a comparatively small set of table definitions to a SQL Server instance using Microsoft's dedicated migration tool SSMA. I ran the migration tool previously, having to leave it processing overnight due to the quantity of objects. When I tried to save the project, frustratingly, the machine ran out of memory, taking me back to where I started.
I initially connected as SYSTEM, so created a new user that could select only from the tables for migration, along with CREATE SESSION and CONNECT privileges. This failed on connection to Oracle due to the dictionary tables being inaccessible.
I then added granted SELECT ON ANY DICTIONARY to the new user and connected to the Oracle source. This time, the connection was successful, but I believe the entire dictionary is being read due to the amount of time it's already taken to load the objects into SSMA.
What I would like to know is: is there an easy way to constrain the set of tables being loaded into SSMA, with the intention of speeding up the connection process?

How to create reports in Access via ADO When data is in SQL Server?

I have an Access 2003 project in which all data is stored in SQL Server 2008. I am using ADO to view/update data via forms that are completely unbound. For example, a form has several textboxes and combo boxes on it. When the form is loaded I use ADO to make a call to a stored procedure on SQL SQL, it returns a recordset and I populate the controls, via VBA, with the data from the recordset. I like this approach because only the VBA is stored within Access. No data (well actually connection strings are stored in Access, but that is it!).
My problem is what to do when it comes to reports. I want to create reports that are based off of views created within SQL Server, however I would like to avoid, if possible, static linking to the views directly from within Access. Is it possible to set the recordsource of a report dynamically at run-time to be the results of a SQL Server view? If it is, how does one go about designing the report id Access does not contain any data?
More info ... The reason I want to avoid linking to the view in Access is the environment in which the Access application could be run changes (Production, Development, Test). Currently whenever I make any calls to the database stored procedures, I look up the connection string (Active Directory based so no passwords are stored) in the only table that is stored in Access .
Thanks for any assistance.
First of all let's be clear: you don't have an Access 2003 "project." You have an Access 2003 database.
An actual Access Data Project cannot have local tables, and uses a SQL Server as the back end. When you view Tables you see the ones that exist on the server, and under Queries you see the views, functions, and stored procedures that exist on the server. You can use the "Upsize Wizard" to turn an Access database into an Access data project (or probably better, just create a new ADP (Access Data Project) and import all the forms, reports, macros, and modules.
Here are my ideas:
Convert the database to an actual Access Data Project and then just use regular old queries as if they were addressed to the local database. You can even bind forms to stored procedures and they can be updatable. To deal with Production, Development, and Test, you just change the connection string in the GUI or you change it through code like so:
Application.CurrentProject.CloseConnection
Application.CurrentProject.OpenConnection NewConnString
If you want to read the connection string from a centralized database or from a text file on a share or from a common table you load in each environment (that has the connection information for every other environment), that is up to. I have one Access Data Project that has an toolbar with an Environment dropdown. When the environment is switched, a child database dropdown is then populated, and finally all open forms are notified by an event (though bound forms close when this occurs).
There's nothing wrong with using linked tables. Just write a procedure that loops through all the tables and updates them to point to the correct server when you want to change environments. The difference between "static" linking and "dynamic" linking is just a single VB procedure that rips through all the tables and relinks them--easy peasy.
Setting a report recordset dynamically at runtime is problematic. It MIGHT be possible in actual Access Data Projects, but definitely not in regular MDBs.
You CAN create pass-through queries in an Access MDB, but I'm not sure about passing parameters in. You'd probably have to set the query text dynamically with the parameters hard-coded and then run the report. This would be a problem for a multi-user database unless each person gets his own front-end to run from.
I recommend that you go with option 1 or 2. Option 1 seems simplest but there is some learning to do before you'll become facile with ADPs over MDBs. Let me know if you think you'll go down that route and I I'll share some of the gotchas with you. However, it's probably easier than what you're doing now which is everything manually. (Ouch!) The second option would be fastest for implementing right away and not throwing any wrenches into your current skill with MDBs.
UPDATE
So if you want to link tables, here's some code to get you started:
Sub TableRelink(MdbPath As String)
Dim Table As DAO.TableDef
Dim Tables As DAO.TableDefs
Set Tables = CurrentDb.TableDefs
For Each Table In Tables
If Table.SourceTableName <> "" Then 'If a linked table
Table.Connect = ";DATABASE=" & MdbPath 'Set the new source
Table.RefreshLink
End If
Next
End Sub
This code is for MDB files, but some digging will quickly give you the correct properties and values to use for SQL Server linked tables.
Another Thought
I just thought of another possible way to handle just the problem you're experiencing: Use a session-keyed "temp" table in Access. Create a local table that has all the columns the view returns, plus a GUID column. When the report is run, insert the contents of the view to the local table, keyed by a new GUID value. Set the recordsource of the report to SELECT * FROM MyViewTempTable WHERE GUID = '{GUID}'. Simple problem solved. On report_close, delete from the table. Perhaps put in a date also and delete after 10 days in case any rows get left behind.

Upsizing a split Access database

I need to upsize a split Access database, i.e., one that's currently split between tow mdb files, a front-end and back-end. I see many webpages that in essence say, "run the Upsizing Wizard." My first, very basic question:
Should I be running this wizard in my front-end mdb or my back-end mdb?
I assume I don't want to link main mdb -> backend mdb -> sql server. Should I run the wizard on the backend mdb, and then in the frontend mdb change the linked tables to point to sql server rather than to the backend mdb? If so, how is this done? When I right-click and go into the Linked Table Manager for a table in the frontend (linked to the backend md), it only seems to let me choose a new mdb file.
I would agree with your first guess: you will want to run the wizard on the back-end mdb.
Once that's in SQL Server, also as you guessed, you'll want to link the front end to work with the SQL Server data. One way to do this is to set up an ODBC data source for your new SQL Server database and select that in the Linked Table Manager.
Open the Data Sources (ODBC) shortcut: in XP Pro, this is in the Control Panel under Administrative Tools. (If you don't see it, you probably don't have permission to create a data source, so you'll have to work with your network people to do this.) This will open the ODBC Administrator.
On the File DSN tab, click Add.... You'll see a list of available drivers. Select SQL Server and click Next. (If the front end is only being used on your machine, you can create a System DSN instead.)
Find a common location and name your data source.
Click Next and Finish. This will set up the first part of the data source, and will open the SQL Server data source wizard.
Name the data source and select the server on which you've put the upsized back-end database.
Change the rest of the settings as needed (you may not need to change much, but the scope of those changes may require a second question) and click through to Finish.
Once you have the data source set up, then Get External Data should give you the option to select it as your source. (In 2007, you can get there from the External Data ribbon. ODBC data sources are available under More.)
To expand a little further based on Matt's follow-up questions:
How you do it is a design choice. I recommend upsizing the back-end mdb because that would allow you to keep whatever forms and such you had in Access; I think it's less of a transition if your data is in SQL Server.
Before you upsized, your tables were linked to the back-end database, and the Linked Table Manager showed the links. After you set up the ODBC data source and linked those tables, it'll show that link. You'll view the links in two different ways because they're actually different types of links (Access vs. ODBC), even though the links may look the same in your front-end mdb.
Personally I have found that the upsizing wizard does a very bad job of determining correct datatypes. I would create the tables myself in SQL server using the datatypes I need, then move the data to the existing tables from Access. other wise you will be stuck with text data when you could use varchar or float when you really need decimal.
Once the data has been moved then I would delete the Access tables and link to the SQL Server tables.
Do not do anything without having a backup copy of the database first.
As a matter of standard paranoia, I would just make a backup copy of the existing files and run the Upsizing Wizard on the front end. If anything undesirable happens, just revert the changes by overwriting with the backup copy.
Update the front end, and it will import the back end tables before it upsizes. I did this a week ago with a successful result.
However, any queries that use -1 instead of Yes will fail. Any full table deletes on tables without a primary key will fail, and you will get different behaviour from that than you will by merely using a pass-through SQL query to truncate table. The trunc will delete all rows, the Access version may leave a blank.
Also you'll need to include dbSeeChanges anywhere you have a recordset opening on a table with an autonumber column data type. SQL changes these to Identity data types, then gripes before you try to open the table. Good luck.
Do it all in the front end
You can simply export the tables to SQL Server.
You can then delete the linked tables you have in your frontend.
Then link the connection to SQL Server
Check:
when you open tables you get records
all your queries run
compile your code
You will also have to consider how you are releasing the front end. If you are using a dsn file you will need to provide that to each user.
You will need to determine how the end user accesses SQL Server. Are you using a single login with the username and password stored in the connection?
You could also split your backend DB into multiple Access DB and link them in the frontend.

Resources