Programmatically create content database in C# (SP 2013) - c#

The goal is to have a web user interface with the option to create new site collections with new Content Database.
With the admin user I can manually in the CA create new Content Databases. I can also create a new site collection in this content database.
The idea was to create an event receiver (C#). If the user adds data to a table, the mentioned actions are to be executed.
Experiments:
a) Console application - works!
using (SPSite site = new SPSite("http://sp2013")) {
using (SPWeb spWeb = site.OpenWeb()) {
SPWebApplication elevatedWebApp = spWeb.Site.WebApplication;
elevatedWebApp.ContentDatabases.Add("sp2013", "WSS_Content_80_" + DateTime.Now.ToString("yyyymmddhhMMss"), null, null, 10, 15, 0);
}
}
b) Event Receiver - Only create site collections works, creation of content databases does not work! Error: Access Denied.
c) Web Service - Does not work! Error: Access Denied.
So, why do I get the error Access Denied when I can create site collections, but only content databases creation not go?
Finally I executed PS Script - but this also doesn´t work.
# AUTHOR: Paul Kotlyar
# CONTACT: unclepaul84#gmail.com
# DESCRIPTION: sets an option on content web service that allows updating of SP Administration objects such as SPJobDefinition from content web applications
function Set-RemoteAdministratorAccessDenied-False()
{
# load sharepoint api libs
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Administration") > $null
# get content web service
$contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
# turn off remote administration security
$contentService.RemoteAdministratorAccessDenied = $false
# update the web service
$contentService.Update()
}
Maybe somebody knows a solution?
I asked the same question in Stackexchange.

This is a permissions problem, but not for clients account. The client user is irrelevant. The problem is that for content database creation your code need farm administrator privileges. However, running code with elevated privileges is insufficient, because when you execute code in this way, SharePoint impersonate with application pool user of correspondent web application.
If the app pool user for "http://sp2013" do not have farm admin privileges, you cannot create content database with an event receiver (maybe for this reason you have an Access Denied error for your event receiver and your webservice code). The problem is giving farm admin privileges to an app pool or service user it's a very bad idea.
I recommend to you implement this solution as timer job. You can create a SharePoint farm solution, and make a timer job, because normally timer jobs are executed with a farm admin account. In this way, you could create a content database.

Related

Impersonation works with local shared file, but does not work with remote one

I have a .net/c# web app (web api) with windows authentication. The service is hosted on my local computer, IIS 10. Application pool identity set to me, currently logged in windows user. Computer is in active directory domain.
I want to access shared file using account, currently logged in to the app. File has appropriate permissions. For this purposes I use impersonation like this:
if (HttpContext.Current.User.Identity is WindowsIdentity windowsIdentity)
{
using (windowsIdentity.Impersonate())
{
FileStream stream = new FileStream(#"\\server\share\file.ext", FileMode.Open, FileAccess.Read);
}
}
I logging in with current windows account, the same as set in app pool identity. This works fine with a shared file on a local computer, where the app is hosted. But does not work with a remote shared file, located on another computer. The other computer is in active directory domain too.
From a hosting computer I can access shared file using windows explorer or my browser. Also if I do not impersonate user, .net trying to access shared file with application pool identity account(set to the same user, me) and it succeeded for both, local and remote files.
It also works with impersonated identity got from LogonUser method from advapi32.dll. But it requires user password and I do not want to request password from user, already logged in to app.
What am i doing wrong?
Update: If a shared file located on hosting machine, then logon event generated by windows (security tab in event viewer) shows the right user. If a shared file located on another machine, then logon event generated by windows on this machine shows the anonymous user. So, account somehow lost.
Update 2: Impersonation works if I run site on IIS like localhost(localhost in url). But if I run it using ip or site name it stops working.
Update 3: Wireshark shows the request for getting ticket(to access shared file server) for delegation fails with error "KRB5KDC_ERR_BADOPTION NT Status: STATUS_NOT_FOUND". Delegation for application pool user allowed in AD.
The same ticket(for cifs/fileshareservername) without delegation can be successfully retrieved(wireshark shows) when doing Dir command in cmd. Seems like problem in AD.
Can't for sure if what you're doing is wrong, but I can tell you what I've done to do a very similar thing. My .Net site doesn't have WindowsLogin normally, so I had to make an extra jump that I think you could do to facilitate the same thing, just perhaps not the best answer.
At login ( in my membershipProvider ) I run this code:
try
{
if (LogonUser(user,domain,password, [AD_LOGIN],
LOGON32_PROVIDER_DEFAULT, ref handle))
{
IntPtr tokenDuplicate = IntPtr.Zero;
if (DuplicateToken(handle, SecurityImpersonation,
ref tokenDuplicate) != 0)
{
// store off duplicate token here
}
}
}
finally
{
if (handle != IntPtr.Zero)
{
CloseHandle(handle);
}
}
then when you need to impersonate, do this:
var context = WindowsIdentity.Impersonate(tokenDuplicate);
try
{
// do your file access here
}
finally
{
context.Dispose();
}
I had to do some funny conversion of that tokenDuplicate variable. It's an integer value but pointing at a specific memory address where the token information is stored. It stays good as long as your logged in.
Why you can't do the impersonate directly on your identity, don't know. I just know it worked for me with a token, and that was my method to get a token I could use for impersonation.
It started working for me with the following settings.
IIS:
Application pool identity set to a specific user(let's say IISUser).
Windows authentication enabled for IIS site. Kernel mode enabled (important!).
All other magic is happening in Active directory:
Computer with shared files has an SPN: cifs/%computer_name%.
Hosting computer(where IIS installed) is trusted for delegation. Delegation tab -> Trust this computer for delegation to specified services only -> Use any authentication protocol. Then select SPN from item 1. Important: you should select computer SPN, not IISUser SPN.
IISUser is trusted for delegation for SPN from item 1.

Windows Service getting access denied exception while writing to Network Drive

I have an interactive windows service which run on a Local System account and with Interact with desktop checkbox checked(this is mandatory for my project as my service needs to invoke .exe with UI ). I am getting an exception as Access denied while writing to network drive. I am passing the UNC path from config file. i tried giving full control access to anonymous user on the folder which i want to access but its still not working. i cannot run my windows service under Network service account or under any other account as suggested in some other posts because i want it interact with desktop check box checked. is there any way to achieve this?
Edit: UNC path of network drive: //server/ABC/pqr
my service should create .txt file in pqr folder. should have access to delete it afterwords too.
i have tried creating anonymous user for pqr folder and giving it full control but still i am getting access denied exception. as i mentioned before i cannot run it under any other account other than local system account because it will automatically disable interact with desktop option in the properties of that service. is there any way to make it run under Network Service Account and still keep it interactive(interact with desktop option checked in the properties of service)?
Try using the following nugget package named SimpleImpersonation
This way you could wrap the code you use to access your remote file location like this:
using (Impersonation.LogonUser(domain, username, password, logonType))
{
// do whatever you want as this user.
}
It worked for me. I used it to turn on and turn off a windows service remotely. Like this:
await Task.Factory.StartNew(() =>
{
using (
Impersonation.LogonUser(serviceInfo.Domain, serviceInfo.User, serviceInfo.Pswd,
Environment.MachineName.Equals(serviceInfo.ComputerName,
StringComparison.InvariantCultureIgnoreCase)
? LogonType.Network
: LogonType.Interactive))
{
var service = new ServiceController(serviceInfo.ServiceName, serviceInfo.ComputerName);
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(60));
}
else
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(60));
}
}
});
(the snippet was taken from the project site)

StreamInsight: Access is denied

I hosted a StreamInsight server to windows service. The windows service run with LocalSystem.
In OnNext() method, I have code access to server
using (
var server =
Server.Connect(
new EndpointAddress(#StreamInsightConfiguration.Default.StreamInsightServiceHostURL))
)
{
var application = server.Applications[StreamInsightConfiguration.Default.StreamInsightApplicationName];
return application;
}
At line server.Applications[StreamInsightConfiguration.Default.StreamInsightApplicationName]; I received a message Access is denied.
I also add NT\SYSTEM to StreamInsightUsers$Default group.
How to fix this problem ?
If a user is logged in while the account is being added to the group, the user must log off and then log on again in order for the group membership to become effective. Users that are not members of this group will receive "access denied" errors when attempting to connect to the server’s Web service endpoint in the Event Flow Debugger and other client programs.
Courtesy:- https://msdn.microsoft.com/en-us/library/ee378749(v=sql.111).aspx

TFS 2010 - Why am I getting "TF30063 You are not authorized to access.." error when impersonating?

I am attempting to create a bug in TFS2010 by impersonating a user but always get
"TF30063 You are not authorized to access.."
I first authenticate using a service account and then attempt to impersonate a separate user account. I can successfully create Work Items using either account both programmatically and in the web UI. However, when I try to create the Work Item used an impersonated account (either way around) I always get this error. My code is:
public int Save(List<KeyValuePair<string, string>> values, ticketType type,string user)
{
// get the Uri to the project collection to use
Uri tfsuri = new Uri("http://94.23.12.119:8085/tfs");
// get a reference to the team project collection (authenticate as generic service account)
using (var tfs = new TfsTeamProjectCollection(tfsuri, new System.Net.NetworkCredential("username", "password", "servername")))
{
tfs.EnsureAuthenticated();
//Now get the details of the user we want to impersonate
TeamFoundationIdentity identity = GetImpersonatedIdentity(tfsuri,tfs,user);
//Now connect as the impersonated user
using (TfsTeamProjectCollection ImpersonatedTFS = new TfsTeamProjectCollection(tfsuri, identity.Descriptor))
{
ImpersonatedTFS.EnsureAuthenticated();
var workItemStore = GetWorkItemStore(ImpersonatedTFS);
// create a new work item
WorkItem wi = new WorkItem(GetWorkItemType(type, workItemStore));
{
//Values are supplied as a KVP - Field Name/Value
foreach (KeyValuePair<string,string> kvp in values)
{
if (wi.Fields.Contains(kvp.Key))
{
wi.Fields[kvp.Key].Value = kvp.Value;
}
}
ValidationResult = wi.Validate();
}
if (ValidationResult.Count == 0)
{
wi.Save();
return wi.Id;
}
else
{
return 0;
}
}
}
}
It successfully gets the impersonated identity but falls over on
ImpersonatedTFS.EnsureAuthenticated();
Both accounts have the 'Make requests on behalf of others' permission set.
First let me clarify one thing first. It seems your application is a server application, in which case there is no value in using EnsureAuthenticated(). It is just a performance tuning trick to help UI/desktop clients.
Now back to your main issue:
- If your application works as expected when you access locally but fails when you access remotely, then please read on, otherwise this is not the solution for you.
The reason it is failing is because the SPN needs to be added to the service account on the active directory. It is necessary for Kerberos authentication to take place.
This is something that TFS team needs to explain because many developers will forget about it while focusing at the job it hand. Hope this helps.
To learn more about SPN's and Kerberos fundamentals, check out these resources:
Kerberos for the busy admin.
Introduction to Kerberos SPN
I hope this helps.
Thanks!
Where do your users have the Make requests on behalf of others permission set? Is it at the Project Collection level (accessed via Team > Team Project Collection Settings > Security..) or at the TFS server level (accessed via Team Foundation Administration Console > Application Tier > Security..) ?
I think your problem is that you only have permission to impersonate at the 'Server' level, but you're trying to impersonate in a collection.
This is what Taylor has to say in his Introducing TFS Impersonation blog post:
This permission is encapsulated within each Team Project Collection
and within the Configuration Server. This means that if User A has
this permission on TPC1 he will not be allowed to impersonate users
when talking to TPC2 or the Configuration Server. Similarly, if User
B has this permission on the Configuration Server she will not be able
impersonate users when talking to any of the Team Project Collections.

SharePoint security programming issue

I am using SharePoint Server 2007 Enterprise with Windows Server 2008 Enterprise. I have deployed a publishing portal. I am developing a ASP.Net web application using VSTS 2008 + C# + .Net 3.5 + ASP.Net + SharePoint Server 2007 SDK.
I found sometimes we need to use SPWebApplication.FormDigestSettings.Enabled = false in order to walk around, e.g. using SharePoint API to create a site in a site collection. I want to know why we need to execute SPWebApplication.FormDigestSettings.Enabled = false? What is the reason behind the scene?
thanks in advance,
George
Does the user that is executing the commands have permissions to run the commands? Based on documentation, it appears that you are disabling security validation when you set that property to false.
A better way to get "super user" permissions to execute a command that the current user doesn't have permissions to run is to use SPSecurity.RunWithElevatedPrivileges
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Note: It's important that you create all new SPSite and SPWeb
// objects in the elevated context in order to actually use elevated
// privileges. Failure to do so will cause your code to execute
// without elevated privileges.
using(SPSite site = new SPSite(SPContext.Current.Site.ID))
{
using(SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
{
// run code here that requires elevated privileges.
}
}
});

Categories

Resources