Add column to SharePoint Online 2013 list via Powershell v3 - sharepoint

Can anybody tell me how to do this? None of the examples I have found seem to work.
My site is https://blah.sharepoint.com/technology and my list is called 'pfa'. I want to add some text columns.
I DO have connectivity with SharePoint Online via my Powershell, as I have managed to get some results back from various commands.
Thanks.

How to provision field in SharePoint Online via CSOM in PowerShell
CSOM API comes with:
FieldCollection.Add method - adds a field to the field
collection
FieldCollection.AddFieldAsXml method - creates a field based on
the specified schema, Boolean value, and field options
to add a list or site column.
The example below demonstrates how to add GeoLocation field into Contacts List:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
function Provision-Field([Microsoft.SharePoint.Client.ClientContext]$Context,[string]$ListTitle,[string]$FieldSchema)
{
$list = $Context.Web.Lists.GetByTitle($ListTitle)
$List.Fields.AddFieldAsXml($FieldSchema,$true,[Microsoft.SharePoint.Client.AddFieldOptions]::AddFieldToDefaultView)
$Context.Load($List)
$Context.ExecuteQuery()
}
$UserName = "username#contoso.onmicrosoft.com"
$Password = Read-Host -Prompt "Please enter your password" -AsSecureString
$URL = "https://contoso.sharepoint.com/"
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($URL)
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$Password)
$Context.Credentials = $Credentials
Provision-Field $Context "Contacts" "<Field Type='Geolocation' DisplayName='Location'/>"
How to provision field in SharePoint Online via REST in PowerShell
Endpoints:
http://<site url>/_api/web/fields('<field id>')
http://<site url>/_api/web/lists(guid'<list id>')/fields('<field id>')
The article Consuming the SharePoint 2013 REST API from PowerShell describes how send HTTPS requests to SharePoint REST web services.
Using the Invoke-RestSPO function from the article, the following example demonstrates how to add Note field to List using REST API in PowerShell:
Function Add-SPOField(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password,
[Parameter(Mandatory=$True)]
[String]$ListTitle,
[Parameter(Mandatory=$True)]
[String]$FieldTitle,
[Parameter(Mandatory=$True)]
[System.Int32]$FieldType
)
$fieldMetadata = #{
__metadata = #{'type' = 'SP.Field' };
Title = $FieldTitle;
FieldTypeKind = $FieldType;
} | ConvertTo-Json
$Url = $WebUrl + "_api/web/Lists/GetByTitle('" + $ListTitle + "')/fields"
$contextInfo = Get-SPOContextInfo $WebUrl $UserName $Password
Invoke-RestSPO $Url Post $UserName $Password $fieldMetadata $contextInfo.GetContextWebInformation.FormDigestValue
}
. ".\Invoke-RestSPO.ps1" #InInvoke-RestSPO function
$UserName = "username#contoso.onmicrosoft.com"
$Password = Read-Host -Prompt "Please enter your password"
$WebUrl = "https://contoso.sharepoint.com/"
Add-SPOField -WebUrl $WebUrl -UserName $UserName -Password $Password -ListTitle "Documents" -FieldTitle "Comments" -FieldType 3
References
Fields REST API reference
Consuming the SharePoint 2013 REST API from PowerShell

Here is someone who created a list with the CSOM through PowerShell with SharePoint Oneline http://www.hartsteve.com/2013/06/sharepoint-online-powershell/
The PowerShell stuff for SharePoint online is limited to some basic admin tasks only. When you used the CSOM in PowerShell, you can do a lot more.

Related

Get-PnPTenantSite : Attempted to perform an unauthorized operation

Currently we get an access token and then pass this token to PowerShell script to loop across all ODFB personal sites.
$url = "https://XXXXX-admin.sharepoint.com"
$conn = Connect-PnPOnline -Url $url -AccessToken $access_token -ReturnConnection
$sitecollections = Get-PnPTenantSite -IncludeOneDriveSites:$true -Filter "Url -like '-my.sharepoint.com/personal/'" -Connection $conn | Select-Object -ExpandProperty Url
foreach ($site in $sitecollections)
{
....
}
It worked successfully for years until it was broken a while ago.
I tried different versions of PnP PowerShell:
PnP version
Error
SharePointPnPPowerShellOnline 3.21.2005.2 (currently used)
Get-PnPTenantSite : Attempted to perform an unauthorized operation.
SharePointPnPPowerShellOnline 3.29.2101.0
Get-PnPTenantSite : The current connection holds no SharePoint context.
PnP.PowerShell 1.10.28
Get-PnPTenantSite : Attempted to perform an unauthorized operation.
If I change script to use an user/password instead the access token, the script works without problems:
$url = "https://XXXXX-admin.sharepoint.com"
$User = "admin#mydomain.com"
$PWord = ConvertTo-SecureString -String "Password" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
$conn = Connect-PnPOnline -Url $url -Credentials $Credential -ReturnConnection
$sitecollections = Get-PnPTenantSite -IncludeOneDriveSites:$true -Filter "Url -like '-my.sharepoint.com/personal/'" -Connection $conn | Select-Object -ExpandProperty Url
foreach ($site in $sitecollections)
{
....
}
So the error happens when the script connects to SP Online using an access token.
Perhaps the some things were changed. But what exactly? Have some scope to be added when an access token is requested?
Or have some new permissions to be added for the application in Azure AD?
Update:
Modified the script (added Write-Output "Connection is:" $conn | fl) to provide more details about connection and got the difference in ConnectionType property when SharePointPnPPowerShellOnline 3.21.2005.2 is used:
When an access token is used (and the script doesn't work properly), ConnectionType : O365
When an access token is used (and the script works fine), ConnectionType : TenantAdmin

How to check which Azure Active Directory Groups I am currently in?

It is possible to return a list that shows all the Azure AD groups the current account is belonging to?
Both using Azure portal web UI and PowerShell are appreciated!
Here's a few different ways other than using the Portal
Azure AD PowerShell Module
Get-AzureADUserMembership
$user = "user#domain.com"
Connect-AzureAD
Get-AzureADUserMembership -ObjectId $user | Select DisplayName, ObjectId
Microsoft Graph PowerShell Module
Get-MgUserMemberOf
$user = "user#domain.com"
Connect-MgGraph
(Get-MgUserMemberOf -UserId $user).AdditionalProperties | Where-Object {$_."#odata.type" -ne "#microsoft.graph.directoryRole"} | ForEach-Object {$_.displayName}
Microsoft Graph API HTTP Request through PowerShell
List memberOf
$user = "user#domain.com"
$params = #{
Headers = #{ Authorization = "Bearer $access_token" }
Uri = "https://graph.microsoft.com/v1.0/users/$user/memberOf"
Method = "GET"
}
$result = Invoke-RestMethod #params
$result.Value | Where-Object {$_."#odata.type" -ne "#microsoft.graph.directoryRole"} | Select DisplayName, Id
Microsoft Graph Explorer
GET https://graph.microsoft.com/v1.0/users/user#domain.com/memberOf
For Portal, simply click on the user for which you want to find this detail and then click on "Groups" button.
If you want to use PowerShell, the Cmdlet you would want to use is Get-AzureADUserMembership.

Azure Activity Log

I want to monitor who made a change in rbac assignment, I created powershell script for collection data from Azure Activity Log. I used below piece of code. Using this solution I am able to get items like:
caller - user who made a role assignment change,
timestamp,
Resource name - on this resource assignment change has been provided,
action type - write or delete
In Activity Log panel in Azure portal, in Summary portal (Message: shared with "user info"), I can see name of a user who has been granted permissions/assignment to the resource, but using my powershell script I am not able to catch this information, is there any method to get this info?
Get-AzureRmLog -StartTime (Get-Date).AddDays(-7) |
Where-Object {$_.Authorization.Action -like
'Microsoft.Authorization/roleAssignments/*'} |
Select-Object #{N="Caller";E={$_.Caller}},
#{N="Resource";E={$_.Authorization.Scope}},
#{N="Action";E={Split-Path $_.Authorization.action -leaf}},
EventTimestamp
script output:
Caller : username#xxx.com
Resource :/subscriptions/xxxx/resourceGroups/Powershell/providers/Microsoft.Compute/virtualMachines/xx/providers/Microsoft.Authorization/roleAssignments/xxxx
Action : write
EventTimestamp : 8/29/2019 10:12:31 AM
Your requirement of fetching the user name to whom the RBAC role is assigned is currently not supported using Az PowerShell cmdlet Get-AzLog or Get-AzureRmLog.
However, we can accomplish your requirement by leveraging Azure REST API for Activity Logs - List and Az PowerShell cmdlet Get-AzureADUser.
In this way as we are depending on Azure REST API for Activity Logs - List (but looks like you want PowerShell way of accomplishing the requirement) so call the REST API in PowerShell as something shown below.
$request = "https://management.azure.com/subscriptions/{subscriptionId}/providers/microsoft.insights/eventtypes/management/values?api-version=2015-04-01&`$filter={$filter}"
$auth = "eyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$authHeader = #{
'Content-Type'='application/json'
'Accept'='application/json'
'Authorization'= "Bearer $auth"
}
$Output = Invoke-RestMethod -Uri $request -Headers $authHeader -Method GET -Body $Body
$ActivityLogsFinalOutput = $Output.Value
Develop your PowerShell code to get "PrincipalId" (which is under "properties") from the output of your Azure REST API for Activity Logs - List call. The fetched "PrincipalId" is the ObjectID of the user whom you want to get ultimately.
Now leverage Az PowerShell cmdlet Get-AzureADUser and have your command something like shown below.
(Get-AzureADUser -ObjectID "<PrincipalID>").DisplayName
Hope this helps!! Cheers!!
UPDATE:
Please find PowerShell way of fetching auth token (i.e., $auth) that needs to be used in above REST API call.
$ClientID = "<ClientID>" #ApplicationID
$ClientSecret = "<ClientSecret>" #key from Application
$tennantid = "<TennantID>"
$TokenEndpoint = {https://login.windows.net/{0}/oauth2/token} -f $tennantid
$ARMResource = "https://management.core.windows.net/";
$Body1 = #{
'resource'= $ARMResource
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept'='application/json'}
Body = $Body1
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
$token | select access_token, #{L='Expires';E={[timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.expires_on))}} | fl *
I see this new way as well but I didn't get chance to test this out. If interested, you may alternatively try this or go with above approach.
UPDATE2:
$ActivityLogsFinalOutput| %{
if(($_.properties.responseBody) -like "*principalId*"){
$SplittedPrincipalID = $_.properties.responseBody -split "PrincipalID"
$SplittedComma = $SplittedPrincipalID[1] -split ","
$SplittedDoubleQuote = $SplittedComma[0] -split "`""
$PrincipalID = $SplittedDoubleQuote[2]
#Continue code for getting Azure AD User using above fetched $PrincipalID
#...
#...
}
}
Does this work for you?
Get-AzureRmLog -StartTime (Get-Date).AddDays(-7) |
Where-Object {$_.Authorization.Action -like 'Microsoft.Authorization/roleAssignments/*'} |
Select-Object #{N="Caller";E={$_.Caller}},
#{N="Resource";E={$_.Authorization.Scope}},
#{N="Action";E={Split-Path $_.Authorization.action -leaf}},
#{N="Name";E={$_.Claims.Content.name}},
EventTimestamp
My output:
Caller : username#domain.com
Resource : /subscriptions/xxxx/resourceGroups/xxxx/providers/Microsoft.Authorization/roleAssignments/xxxx
Action : write
Name : John Doe
EventTimestamp : 30.08.2019 12.05.52
NB: I used Get-AzLog. Not sure if there is any difference between Get-AzLog and Get-AzureRmLog.
Fairly certain this wouldn't be exposed with this cmdlet. I dont even see this information in the Role Assignments. So not sure what do you mean exactly.

Adding Sharepoint user remotely PowerShell script

Running EnsureUser on an existing domain account give an error that the user could not be found. Same command(s) works fine in PowerShell on SharePoint server locally. I am able to create a SharePoint group remotely, just can't add a user to that group.
$site = new-object Microsoft.SharePoint.SPSite("http://sharepoint.company.com/dev")
$web = $site.OpenWeb()
function GrantUserpermission($userName)
{
$folder.BreakRoleInheritance("true")
$web.SiteGroups.Add("test_group", $web.Site.Owner, $web.Site.Owner, "Desc")
$ownerGroup = $web.SiteGroups["test_group"]
$ownerGroup.AllowMembersEditMembership = $true
$ownerGroup.Update()
$sitename = Get-SPWeb http://sharepoint.company.com/dev
$EnsuredUser = $sitename.EnsureUser("domain\user")
Set-SPUser -Identity $EnsuredUser -web $sitename -group "test_group"
$AddGroup = $web.SiteGroups["test_group"]
$roleAssignment = new-object Microsoft.sharepoint.SPRoleAssignment($AddGroup)
$roleDefinition = $web.RoleDefinitions["Contribute"]
$roleAssignment.RoleDefinitionBindings.add($roleDefinition)
$folder.RoleAssignments.Add($roleAssignment)
$folder.SystemUpdate()
Check if the domain user exists before use the EnsureUser method.
If you want to add SharePoint user to group in remote server, we can use CSOM with PowerShell to achieve it.
$url="http://sharepoint.company.com/dev"
$userName="administrator"
$password="**"
$domain="test"
$sGroup="test_group"
$sUserToAdd="domain\user"
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object System.Net.NetworkCredential($userName,$password,$domain)
$ctx.Credentials = $credentials
$groups=$ctx.Web.SiteGroups
$ctx.Load($groups)
#Getting the specific SharePoint Group where we want to add the user
$group=$groups.GetByName($sGroup)
$ctx.Load($group)
#Ensuring the user we want to add exists
$user = $ctx.Web.EnsureUser($sUserToAdd)
$ctx.Load($user)
$userToAdd=$group.Users.AddUser($user)
$ctx.Load($userToAdd)
$ctx.ExecuteQuery()

Disable all site creation except for a certain group

I want to lock down site creation to a certain group of admin suresh. We have created a group for this, but what do I tell the SharePoint Admin to do in order to achieve this?
To lock down site creation, you basically need to run a few PowerShell commands as below using Azure AD PowerShell. Run them commands with Global admin priviledges.
I am assuming that you have created an Azure AD group with certain users who will have access to create the site.
$creds = Get-Credential
Connect-AzureAD -Credential $creds
$group = Get-AzureADGroup -All $True | Where-Object {$_.DisplayName -eq "ENTER GROUP DISPLAY NAME HERE"}
$policySetting = Get-AzureADDirectorySetting | where-object {$_.displayname -eq "Group.Unified"}
if($policySetting -eq $null) {
$template = Get-AzureADDirectorySettingTemplate | Where-Object {$_.DisplayName -eq "Group.Unified"}
$settings = $template.CreateDirectorySetting()
$settings["EnableGroupCreation"] = $false
$settings["GroupCreationAllowedGroupId"] = $group.ObjectId
$policySetting = New-AzureADDirectorySetting -DirectorySetting $settings
}
else{
$policySetting["EnableGroupCreation"] = $false
$policySetting["GroupCreationAllowedGroupId"] = $group.ObjectId
Set-AzureADDirectorySetting -Id $policySetting.Id -DirectorySetting $policySetting
}
Links:
Installing the Azure AD module
Code modified from - Managing Office 365 group creation using Azure AD PowerShell v2

Resources