Grant permissions to folder in Sharepoint library using Powershell? - security

I have a Sharepoint Library, which I have a Powershell script dropping files into for processing. The Powershell script reaches out to Active Directory, and returns Group Membership information. The script then creates a folder for the group owner (if it doesn't exist) in my Library, using the group owners' name, and drops a .CSV of all the users contained in the specific group into that folder.
The need here, is to grant 'Read' permissions only to the owner of the group, which will be the name of the folder we are working in. Ideally the folder would be hidden, however I understand that there are limitations when working with Sharepoint.
For example:
John Doe, User: jdoe would be able to access Z:/jdoe/IT.csv but not
Z:/someuser/HR.csv
I have my Sharepoint Library mapped to Z:/ currently, to make my life easier for Powershell.
I executed get-command Module Microsoft.SharePoint.PowerShell | ft name and ran through the list of Sharepoint Commands.
I then stumbled across the Grant-SPObjectSecurity Cmdlet, which I assume is what I would want to use on the Powershell side to, when the folder is being created, apply Sharepoint permissions only to the user for which the folder is being created for.
The process from start to finish is: Powershell Script 'Get_Group_Members' executes, reading a text file containing an Active Directory Group name, per line. For each group found, the script identifies the owner of the group, creates a folder named with the owners AD name, and puts a .CSV file in the folder listing all members of the group. Then, I (for now anyway) manually initiate the next Script 'Import_CSV' which pulls all the information into a Sharepoint list for an unrelated process.
Hope that helps understand what's happening. Am I right in assuming I should handle this on the Powershell side, as opposed to the Sharepoint side? If so, am I headin' in the right direction with Grant -SPObjectSecurity?
Thanks!
Update:
Following the link I provided in a comment below, here is what I came up with:
function GrantUserpermission($strOwnerName)
{
[Microsoft.SharePoint.SPUserCollection]$spusers=[Microsoft.SharePoint.SPUserCollection]$web.SiteUsers
[Microsoft.SharePoint.SPUser]$spuser=$spusers[$strOwnerName]
"Strowner name: " + $strOwnerName
# Get the SPWeb object and save it to a variable
$web = Get-SPWeb -identity $WebURL
if ($strOwnerName -ne $null)
{
$sproleass=new-object Microsoft.SharePoint.SPRoleAssignment([Microsoft.SharePoint.SPPrincipal]$spuser)
$folder.BreakRoleInheritance("true")
$sproleass.RoleDefinitionBindings.Add($web.RoleDefinitions["Contribute"])
$folder.RoleAssignments.Add($sproleass);
Write-Host "Permission provided for user ", $strOwnerName
}
else
{
Write-Host "User ""$userName"" was not found in this web!"
}
}
And here, are the error(s) associated with my code:
Full code can be found here: http://pastebin.com/iBpj6V1U
Update #2
#apply permissions to folder
"Strowner name: " + $strOwnerName
function GrantUserpermission($strOwnerName)
{
$web = Get-SPWeb -identity $WebURL
[Microsoft.SharePoint.SPUser]$spuser=$web.EnsureUser($strOwnerName)
"Strowner name in Function: " + $strOwnerName
Updated code #2: http://pastebin.com/DzP1hVce

I ended up realizing, that if I am using Powershell to get information to a .CSV, and then ultimately to Sharepoint, that it doesn't make sense to actually waste time with files, and tap directly into Sharepoint via Powershell.
Here's the code I had used to accomplish this: http://pastebin.com/xRyvXLCB
Special thanks to #TheMadTechnician

Related

Azure AD Group and SharePoint

I'm having an issue with the timing around creating a new Azure AD security group and using that group for SharePoint Online folder access.
Using New-PnPAzureADGroup i'm creating the security group, then using Set-PnPListPermission and Set-PnPFolderPermission i'm setting the security group with the required permission for that List or Folder.
It seems that Set-PnPListPermission & Set-PnPFolderPermission are running too quickly after the creation of the group as it reports
Set-PnPListPermission : The specified user XXXX123_SP could not be found.
The strange thing is, once the group has been created I can immediately run Get-PnPAzureADGroup and retrieve the group. I can also manually run the same command a little later and it completes successfully.
I assume the groups take time before they're available in SharePoint, what's the best practice approach to check and wait for these groups before applying them in SharePoint?
Thanks in Advance
You could try to use following PnP PowerShell commands:
Set-PnPListPermission -Identity '$LibraryName' -User 'c:0t.c|tenant|$AdGroupID' -AddRole 'Read'
I replaced -Group with -User in the PnP PowerShell command. Then executed successfully with on error message.
I've encountered this issue, except with external users rather than AD Groups but I think the root is the same. The object can be immediately queried from AD but takes times to become resolvable in SharePoint.
I doubt you'll find a documented best practice as this is a bit of an advanced use case. In my case I seem to recall it taking between 5 and 30 seconds to resolve. What I did was loop 10 times with a Thread.Sleep and break out when it succeeds. Event then you'd get occasional failures - you just log them and move on and let support staff deal with it.
Not my proudest coding moment but it (mostly) got the job done.
$condition = $false
do{
try {
Set-PnPListPermission [-ErrorAction Stop]
Set-PnpFolderPermission [-ErrorAction Stop]
$condition = $true
}
catch {}
}
until{$condition}

How can I retrieve files within a repo in Azure within a Powershell script?

I need to (within a Powershell script) determine all the possible controller file names within a repository. This is for a test that will hit every controller and verify it is functioning and not missing from the startup file. (MVC app)
Since all the files are DLLs I cannot simply ask for the files in the folder nor do I want to hard code the names. How can I get a listing of files within a certain folder in order call each one to test within a powershell script?
Perhaps a better way to ask this is:
How can I list files within a folder that is inside a repo? (using a Powershell script)
You could refer to this doc:Interacting with Azure Web Apps Virtual File System using PowerShell and the Kudu API. It uses the VFS API in the wiki doc. And there is a api to list files at directory specified by path.
GET /api/vfs/{path}/
Lists files at directory specified by path.
And in the previous doc, under the title Downloading a File from an App Service, there is a scripts to download the files. I use the path without $kuduPath to list files. And you need to Getting the Kudu REST API Authorisation header via PowerShell. And then the scripts would be like this.
$kuduApiUrl="https://<webname>.scm.azurewebsites.net/api/vfs/site/wwwroot/"
Invoke-RestMethod -Uri $kuduApiUrl `
-Headers #{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
-Method GET `
-OutFile $localPath `
-ContentType "multipart/form-data"
And here is the result pic.It will list all files and the folders.
hope this could help you, if you still have other questions,please let me know.

How can I run a exchange powershell command with different credentials through Node.js?

Context:
I'm creating a Electron React Application. I'm building it for my colleagues.
This app will give you a simple to use UI. You can do different things for which you normally would need powershell.
Example: Gui asks you for a user you want to access and another user that it should grant access too.
I'm then passing everything we need to powershell-node (a package that handles powershell with node) and it will (in this example) grant Full Access Permissions to the user specified.
The Problem
We are using a different account to fire exchange and powershell commands since we don't have rights with our personal logon. So normally I would create a pssession to our ex server like this:
$Connection = #{
ConfigurationName = 'Microsoft.Exchange'
ConnectionUri = 'http://ourserver/powershell'
Authentication = 'Kerberos'
Credential = Get-Credential}
$Ex2010Session = New-PSSession #Connection
Import-PSSession $Ex2010Session -AllowClobber | Out-Null
Normally this would work and give me the commandlet add-mailboxpermission.
Also the command itself works on a normal powershell because I open it with my Admin account (run as). And that's the point:
In my script I do exactly this but then afterwards I run the Add-Mailboxpermission command with all required parameters.
Of course it won't work because I opened my electron app with my normal account. Also there is not -Credential parameter on the Add-MailboxPermission command.
A possible solution;
The first idea that comes into my mind is, to just open the app with the adm account. While possible I'm aspire for a better solution.
What have I tried
The next idea I got is "Why don't I just send the command to the server via invoke-command like this:
Invoke-Command -Session $Ex2010Session -ScriptBlock {
Add-MailboxPermission -Identity $Identity -AccessRights 'FullAccess' -user
$User -automapping $Automapping
}
Unfortunately when I try to run this I get this error message:
variable that cannot be referenced in restricted language mode or a Data section is being referenced. Variables that
can be referenced include the following: $PSCulture, $PSUICulture, $true, $false, and $null.
I don't have any access to our ex infrastructure and therefore can't try to fix it on these side of problems (language mode).
So there I am, having no idea how to solve this problem. I hope you guys have any ideas how to fix it, that would be very neat.
Little Screenshot of the app:

How do I modify the Site Collection in SharePoint 2013?

When I try to open a form published from InfoPath I now get this error:
"The following location is not accessible, because it is in a different site collection:
https//portal/sites/forms/Daily%20Activity/Forms/template.xsn?SaveLocation=https//portal.alamedacountyfire.org/sites/forms/Daily%20Activity/&Source=https//portal.alamedacountyfire.org/sites/forms/Daily%2520Activity/Forms/AllItems.aspx&ClientInstalled=false&OpenIn=Browser&NoRedirect=true&XsnLocation=https//PORTAL/sites/forms/Daily%20Activity/Forms/template.xsn."
Correlation ID:12c0ab9c-caff-80a8-f1b4-64d81dcfa6ea
Following are some options that you can try:
1) Save the form template (.xsn) as the source files in the publish options. Look at the manifest file in notepad and see if you can find a reference to the incorrect location. If so, correct it and Republish the form.
2) Clear the InfoPath cache on that machine. Start->Run "infopath /cache clearall"
3) See if the site collection has a managed path, if so, give the proper url while publishing. The XSN might be getting deployed on the root site and throws error since the intended list does'nt exist.
I found this worked for me. Got the answer from another post.
"I had a similar problem and found it was due to the request management service routing from my web application host header to the server name.
There was a routing rule in my request management settings. I just disabled routing and the problem went away. I used the following powershell to disable it. "
$w = Get-SPWebApplication "http://webapphostname"
$r = $w | Get-SPRequestManagementSettings
$r.RoutingEnabled = $false
$r.Update()
You may want to configure it rather than disable it. Here’s a good resource to get you started:
http://www.harbar.net/articles/sp2013rm1.aspx

WMI/PowerShell Bug: why is CreateSite creating *two* sites all of the sudden?

I have a simple PowerShell script that uses WMI to create a web site on a Vista box. Yes, I know PowerShell has an IIS provider for working with IIS 7, but this script must also support IIS 6.0, so that rules that out.
Anyway, the script was working just fine, but all of the sudden (and I mean that literally, I made zero code changes to the script) it started creating a second, broken site for every call to the CreateNewSite method. Below is the script. Anyone have any ideas?
$path = "C:\My Path\WebSite"
$site = "TestSite"
$hostHeader = "demo.blah.com"
$service = Get-WmiObject -namespace "root\MicrosoftIISv2" -class "IIsWebService"
$bindingClass = [wmiclass]'root\MicrosoftIISv2:ServerBinding'
$bindings = $bindingClass.CreateInstance()
$bindings.IP = ""
$bindings.Port = "80"
$bindings.Hostname = $hostHeader
$result = $service.CreateNewSite($site, $bindings, $path)
The above script was just creating a site named 'TestSite', but now it's also creating a site called 'SITE_1786339847' (the number changes, but it's always similar to that). I have stepped through the script executing one line at a time, and neither site is created until the CreateNewSite method is invoked. Is WMI just buggy?
Whoops, answered my own question. I checked the raw IIS 7.0 configuration file and found an orphaned virtual directory that was associated to a site with the ID 1786339847. When I removed that virtual directory from the configuration file, the script started working correctly again.
In case anyone runs into something similar, grab the site ID for the bad site from IIS Manager before deleting it, then open up C:\Windows\system32\inetsrv\config\applicationHost.config. Scan the file for that ID and look for any orphaned references to it. Be sure you have a backup first.

Resources