Add an Office365 user to the Role Group "View-Only Organization Management" - c#

I am trying to add an Office365 User to the Role-Group, "View-Only Organization Management" from client side using C# and PowerShell. I have installed the Azure AD on my local machine. After which, I am able to run the following cmdlets both from PowerShell as well as my Console app:
Connect-MsolService
New-MsolUser
Add-MSOLRoleMember
Now, to add the User, to the Role-Group, "View-Only Organization Management", I tried to use the cmdlet, Add-RoleGroupMember in the format,
Add-RoleGroupMember "View-Only Organization Management" -Member PK
PK is the display name of the User. But when I execute this cmdlet from PowerShell or my Console app, I am getting the following error:
So how can I achieve this? Thanks in advance.

I figured out that none of the "Exchange 2013" cmdlet will not be present on our machine by default., We need to import the Powershell Session before using the cmdlet and then to remove it when we're done using it. Below is the complete set of commands needed to perform this task:
Open Windows Powershell.
Get the credentials.
$Cred = Get-Credential
Create a remote PowerShell session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $UserCredential -Authentication Basic –AllowRedirection
Plz make sure that the url given above is for Exchange Online only.
Import the cmdlets to the PowerShell
Import-PSSession $Session
Once the import is done, all the Exchange 2013 cmdlets become available.
We can then execute the cmdlet, "Add-RoleGroupMember"
Add-RoleGroupMember -identity "View-Only Organization Management" -member PKS
Finally, don't forget to remove the Session before exiting.
Remove-PSSession $Session
The only difference was that earlier I was not importing the PSSession before executing this cmdlet. Plz note that import is valid for any Exchange 2013 cmdlet and not just for this only.
For further details, you can visit here.

Related

How to script azure b2c applications creation

I need to create bunch of azure b2c application with powershell scripts.
A powershell script to perform steps described here
https://learn.microsoft.com/it-it/azure/active-directory-b2c/tutorial-register-applications
thank you
Currently, it is only possible to manage B2C policies programmatically. Since B2C Custom Policies went GA, it is now possible to create custom policies using PowerShell.
Refer this: https://stackoverflow.com/a/56252795/10571855
However, the feature request for programmatic app mgmt is here. Please vote for it so that we can let you know when it is available for preview.
You can use PowerShell AzureADPreview 2.0 module to create applications.
Full doc is here: AzureADPreview 2 docs
I had no success to install this module to "old" PowerShell (5.x) so I gave a shot to the 'new' PowerShell 7 (Core). The only issue with PowerShell 7 and AzureAD module is that Connect-AzureAD uses a cryptographic function which is not in .NET Core, so you must import the AzureADPreview module using the -UseWindowsPowerShell option.
Here is a sample, works with PowerShell 7:
Install-Module AzureADPreview
Import-Module AzureADPreview -UseWindowsPowerShell
$tenantId = "yourb2ctenant.onmicrosoft.com"
# Note: this will interactively ask your credentials.
# If you want to run this unattended, use the -Credential parameter with a PSCredential object with a SecureString
Connect-AzureAD -TenantId $tenantId
# ready to go
#list your all apps
Get-AzureADApplication
# examine one of you app and get ideas
$application = Get-AzureADApplication -ObjectId af46a788-8e55-4301-b2df-xxxxxxxxx
# create and application
$applicationName = "yourappname"
$application = New-AzureADApplication -DisplayName $applicationName -PublicClient $true etc

Login to Azure powershell using Connect-AzureRmAccount in a program run in a Post publish event

I have a program that uses the following code (Simplified)
using (PowerShell powerInstance = PowerShell.Create())
{
powerInstance.AddScript("Set-ExecutionPolicy Unrestricted");
powerInstance.AddScript("Connect-AzureRmAccount");
powerInstance.Invoke();
}
This works fine when and a login popup is shown to enter credentials.
Now I want this program to run after I publish my Web app to azure to do this I added a post publish event in my seperate web project like so
<Target Name="PostAzurePublish" AfterTargets="MSDeployPublish">
<Exec Command="C:\MyProgram.exe"></Exec>
</Target>
The issue here is when I publish the my web App the program that runs the powershell commands runs but hangs indefinitely and the Login popup is not shown. So I am assuming it is just waiting for credentials to be supplied but beacuse the login dialog is never shown it hangs.
Is there a simple way I can get the Login dialog to show in this scenario?
You can use Connect-AzureRmAccount PowerShell command without an interactive login. All you have to use is Service Principal for the log-in credentials.
$applicationId = "<service prinicple application id>";
$securePassword = "<service prinicple password>" | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $applicationId, $securePassword
Connect-AzureRmAccount -ServicePrincipal -Credential $credential -TenantId "<your tenantid>"
See my detailed answer here

Windows Store App with powershell

I am developing a windows 8.1 store app and in that i want to get the GAL and add the GAL by using power shell script. When i tried to add the referance to System.Security.SecurityString it is giving an errors like follows.. I am trying to authenticate to with my office365 admin details but it is giving an error while building the app.
'System.Management.Automation.PSCredential' does not contain a constructor that takes 2 arguments
But it contains a constructor with two arguments , The same code works well when i build a windows forms application. What will be the wrong with windows 8.1 app?
System.Uri psURL = new Uri("https://ps.outlook.com/powershell/");
System.Security.SecureString securePassword1 = safeString("test");
System.Management.Automation.PSCredential creds1 = new System.Management.Automation.PSCredential("test", securePassword1);
Questions
1) Is System.Security.SecurityString is compatible with windows 8.1 app or this error coming from PSCredential why because when i removed the securestring referance the PSCredential error not happening but getting securestring error missing like that?
2) Is there any alternative method to connect to powershell without secure string by c# code?
System.Security.SecureString is part of the .NET Framework.
It is not visible in your example code how you convert your string to secure string:
$secure_string_pwd = convertto-securestring "P#ssW0rD!" -asplaintext -force
$username = "username#yourdomain.com"
$cred = New-Object System.Management.Automation.PSCredential $username, $secure_string_pwd
Try to connect to O365 with following code:
Import-Module MSOnline
$O365Cred = Get-Credential
$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange
-ConnectionUri https://ps.outlook.com/powershell -Credential $O365Cred
-Authentication Basic -AllowRedirection
Import-PSSession $O365Session
Connect-MsolService –Credential $O365Cred
You might also find this article interesting - the example code is taken from there...

How do I host a Powershell script or app so it's accessible via WSManConnectionInfo? (like Office 365)

The only ways I know to connect to a remote runspace include the following parameters
WSManConnectionInfo connectionInfo =
new WSManConnectionInfo(false, "localhost", 80, "/Powershell", "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
or
WSManConnectionInfo connectionInfo =
new WSManConnectionInfo(false, "localhost", 5985, "/wsman", "http://schemas.microsoft.com/powershell/Microsoft.Powershell", credential);
How do I set up my own custom Powershell object so I can expose it through HTTP?
What are the correct parameters to use and how do I set them up?
There are several pieces to this, so I'll explain them separately and then bring them together.
Implicit Remoting
Exchange is using Implicit Remoting.
The way it works is that you establish a PSSession to a remote machine, then import some of the commands available from the remote instance into your own.
This is done using Import-Module -Session $session or Import-PSSession.
You can try this for yourself purely in Powershell. Use a workstation that does not have the Active Directory RSAT installed (doesn't have the ActiveDirectory powershell cmdlets), then connect to a machine that does (let's call it DC1):
$s = New-PSSession -ComputerName DC1
Invoke-Command -Session $s -ScriptBlock { Import-Module ActiveDirectory }
Import-PSSession -Session $s -Module ActiveDirectory
Restricting the call to Import-PSSession to just the one module lets you import just those cmdlets. At this point you would be able to execute Get-ADComputer for example, as though it were available locally, even though the actual call is being done on DC1.
Session Configurations
When you make a powershell remoting connection, you are connecting to a session configuration. If you don't specify one, you connect to one called Microsoft.PowerShell. To see all of the configurations that are defined on a machine, call Get-PSSessionConfiguration. You might see some others, for example Microsoft.PowerShell32 is a way to connect to a 32 bit powershell session.
To connect to a specific configuration, use New-PSSession -ConfigurationName or New-PSSession -ConnectionUri.
Defining Session Configurations
You can specify a lot of stuff in a session configuration; the version of powershell, the bitness, which modules are pre-imported, you can pre-define functions and code, you can prevent language features from being available, etc.
This answer provides a good overview of how to create your own configuration.
You can also put configuration information inside of an assembly, which would work well for what you're trying to do.
Wrapping Code in Modules
As you've seen with Import-PSSession it's easier to import just the code you want if it exists in a module. Therefore you should make sure that your cmdlet is exposed through a module.
You said in a comment that you wanted to write your cmdlet in C#. This is not something I've done, but this article appears to provide detailed instructions on how to create a PowerShell Module in C#.
This is now something I have done (and that article is good). Writing a cmdlet in C# is, implicitly, already a module. In fact, you can use Import-Module to load a compiled .NET assembly, whether it contains any PowerShell cmdlets or not.
For example if you created a public class and compiled it into a DLL, you can do Import-Module MyAssembly.dll and that class is now available in your PowerShell session.
Defining the cmdlet in C# means including a reference to System.management.Automation and then creating a class that inherits from Cmdlet or PSCmdlet.
Defining the module manifest is recommended but technically optional, just as it is with a script module.
I have not however included the session configuration information in an assembly (yet?), nor have I seen a reference for how to do that.
Bringing it Together
The steps should roughly resemble this:
Compile module and make it available on the remote end, so that it can be imported to powershell from a local session on that machine.
Create a new PSSession configuration file, and specify either -AssembliesToLoad or -ModulesToImport (or both if necessary), or specify the configuration information in the assembly itself (probably preferred here).
Register the configuration on the machine.
On the client side, you wanted to make it available to PowerShell, so you would simply create the session, then import it:
$s = New-PSSession -ComputerName RemoteMachine -ConfigurationName MyConfig
# The configuration was defined in such a way
# that your module will already be imported in the remote session.
Import-PSSession -Module MyModule
Simplifying it?
You don't have to create a custom configuration on the remote side. As long as your module is available to any powershell session on the remote machine, you can skip the session configuration steps, and then you would just do:
$s = New-PSSession -ComputerName RemoteMachine
Invoke-Command -Session $s -ScriptBlock { Import-Module MyModule }
Import-PSSession -Session $s -Module MyModule
But you may want the additional customization and control you have by using a session configuration, so that's up to you. That's how exchange does it, but it may be overkill for your purposes.

Copying files to remote server with a Setup Project

I am trying to create a setup package that not only installs our app but also copies files to a remote app server and installs a service there. I thought that I would just override the install method in a custom action to have it kick off a powershell script to copy the files. Unfortunately when the code calls the powershell script I get this CmdletProviderInvocationException:
The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you.
I was able to copy the code I am using to call the powershell script into a test project and it ran just fine, as I would expect since I have logged in to the server through windows explorer and so my user should be authenticated. I think the reason the script won't work when called by the installer must be that the installer switches users in order to get admin permissions to install the app, and the admin user is not authenticated (although I could be wrong).
Does anyone know how I could get this to work?
Here's the custom action code:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
string scriptLoc = "c:\\sampleLocation";
pipeline.Commands.AddScript("&\"" + scriptLoc + "\\script.ps1\"");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
and here's the script:
$RemotePath = "\\SERVER\C$\Shared\Service"
$Source = "C:\sampleLocation\Service"
Get-ChildItem $Source -Recurse | Copy-Item -Destination $RemotePath
There are two major requirements for copying files to a network location:
your custom action should run without impersonation
the network location should have full permissions for Everyone
A MSI installation runs under the local system account. So it doesn't matter if you have permissions or not.
Since it's not easy to give permissions to SYSTEM account from a network machine, the easiest approach is to give full permissions to Everyone. This needs to be done on the machine which contains the shared folder.
According to #Cosmin Pirvu and Microsoft documentation :
The LocalSystem account is a predefined local account used by the service control manager. It has extensive privileges on the local computer, and acts as the computer on the network.
If your shared folder is on a computer that is on a domain, you can give full permissions to the client computer in spite giving it to Everyone.

Categories

Resources