Azure Provisioning - Without manual login - powershell

I have a Powershell script which runs to set up Azure web apps, databases, etc. but before running the script, I have to do the following:
PS C:/> Login-AzureRmAccount
This pops up a GUI in which I have to manually add in my user, password, and my 2-factor authentication code. I eventually want to use that script as a part of a part of a build/deployment automation script.
I gleaned the following from a few articles about using a "service principal".
First I do:
PS C:\> Add-AzureRmAccount
In this call I have to put in my user, password, and authentication code
After that I have to do the following (even though I don't fully understand).
$app = New-AzureRmADApplication -DisplayName "GGReal" -HomePage "https://www.example.org/ggreal" -IdentifierUris "https://www.example.org/ggreal" -Password "mysecretpass"
New-AzureRmADServicePrincipal -ApplicationId $app.ApplicationId
This seems to work:
Then I try this, and it fails.
New-AzureRmRoleAssignment -RoleDefinitionName Reader -ServicePrincipalName $app.ApplicationId
I got the following error:
New-AzureRmRoleAssignment : AuthorizationFailed: The client jay#myemail.com' with object id '8ee9a6ec-yyyy-xxxx-xxxx-4ac0883f2a12' does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/write' over scope '/subscriptions/5ba06de5-xxxx-zzzz-yyyy-27f7d2c8bba6'.
At line:1 char:1
+ New-AzureRmRoleAssignment -RoleDefinitionName Reader -ServicePrincipa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureRmRoleAssignment], CloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Resources.NewAzureRoleAssignmentCommand
What do I have to do to enable a scripted authorization without manual intervention?

According to the exception that it indicates that you don't has adequate permission to that. We can check active directory permissions following the document. Our account needs to have Microsoft.Authorization/*/Write access to assign an AD app to a role. That means our account should be assigned to the
Owner role or User Access Administrator role. If not, please ask your subscription administrator to add you to User Access Administrator role. How to add or change Azure administrator roles please refer to the document.
After that please have a try to Automate login for Azure Powershell scripts with the following code.
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Add-AzureRmAccount -Credential $psCred -TenantId $azureTenantId  -ServicePrincipal
I also find some related documents about creating authentication and Built-in roles:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authenticate-service-principal
https://learn.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles#roles-in-azurel

Well, you don't have permissions to assign that role to that serviceprincipal, you need appropriate rights. And those would be: Microsoft.Authorization/roleAssignments/write and scope /subscriptions/5ba06de5-xxxx-zzzz-yyyy-27f7d2c8bba6
You could either create a new Custom Role and assign it to your account, or assign something like Subscription Admin (not sure if its the least possible approach, but you can retract it later) to your account.

Related

Connect-ExchangeOnline UnAuthorized

I'm working on updating our PowerShell scripts to use more secure connection methods. When I try, I get an error that says "UnAuthorized"
PS X:> Connect-ExchangeOnline -AppId $clientId -CertificateThumbprint $thumbPrint -Organization $organization UnAuthorized
At C:\Program
Files\WindowsPowerShell\Modules\ExchangeOnlineManagement\3.0.0\netFramework\ExchangeOnlineManagement.psm1:730 char:21
throw $_.Exception;
CategoryInfo : OperationStopped: (:) [], UnauthorizedAccessException
FullyQualifiedErrorId : UnAuthorized
Is what I highlighted in the following screenshot what I'm supposed to use for the organization parameter?
[snip]
How do I fix the UnAuthorized error?
Thanks
I agree with #scottwtang, you will get unauthorized error if your application don't have required roles and permissions.
I tried to reproduce the same in my environment and got below results:
I used below script from your previous question to generate certificate:
$CN = "GraphApp"
$cert=New-SelfSignedCertificate -Subject "CN=$CN" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -NotAfter (Get-Date).AddYears(5)
$Thumbprint = $Cert.Thumbprint
Get-ChildItem Cert:\CurrentUser\my\$Thumbprint | Export-Certificate -FilePath $env:USERPROFILE\Downloads\GraphApp.cer
Write-Output "$Thumbprint <- Copy/paste this (save it)"
Output:
Now I uploaded this certificate to Azure AD application like below:
For $organization parameter, you need to pass your domain name. You can find that here:
Go to Azure Portal -> Azure Active Directory -> Overview -> Primary domain
When I ran the below script to connect Exchange Online, I got Access denied error like this:
$clientId="47xxxd8-8x2x-4xxx-bxx7-30cxxxxx8"
$thumbPrint="E4A0F6C6B85EBFxxxxxCD91B5803F88E5"
$organization="xxxxxxxx.onmicrosoft.com"
Connect-ExchangeOnline -AppId $clientId -CertificateThumbprint $thumbPrint -Organization $organization
Output:
To resolve the error, you need to add API permission and Directory role to your application:
Make sure to grant admin consent for the added permission as below:
Now I added Exchange Administrator role to my application like below:
Go to Azure Portal -> Azure Active Directory -> Roles and administrators -> Exchange administrator -> Add assignment
It may take few minutes to assign role successfully as below:
Now I connected to Exchange Online by running script again and ran sample command Get-EXOMailbox -PropertySets Archive to verify it and got response successfully like below:
$clientId="47xxxd8-8x2x-4xxx-bxx7-30cxxxxx8"
$thumbPrint="E4A0F6C6B85EBFxxxxxCD91B5803F88E5"
$organization="xxxxxxxx.onmicrosoft.com"
Connect-ExchangeOnline -AppId $clientId -CertificateThumbprint $thumbPrint -Organization $organization
Output:
So, make sure to assign required roles and permissions for your application to fix the error.
Unfortunately Exchange.ManageAsApp no longer appears in the Graph API Permissions, so cannot be directly selected in the portal. But you can add the permission by adding the following to the JSON in the Manifest:
{
"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
"resourceAccess": [
{
"id": "dc50a0fb-09a3-484d-be87-e023b12c6440",
"type": "Role"
}
]
}

Add-AzureRmAccount : Sequence contains no element (Not working for Gmail accounts too)

I have created a 'Free Trial' account with my personal email ID which is a Gmail ID. I'm getting the error :
Add-AzureRmAccount : Sequence contains no elements At line:1 char:1
+ Add-AzureRmAccount -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Add-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.AddAzureRMAccountCommand
The code I'm running is
$username = "abc#gmail.com"
$password = "something"
$secpass = $password | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secpass
Add-AzureRmAccount -Credential $cred
Are there certain type of accounts/subscriptions for which logging in like this is supposed to work?
Windows Live ID credentials cannot be used for a non-interactive login. This error message is described as part of this issue which has been raised because it needs improving.
I think you either need to use Login-AzureRmAccount to login interactively or create a Service Principal for login, per this guide: https://learn.microsoft.com/en-us/powershell/azure/authenticate-azureps?view=azurermps-4.2.0
Log in with a service principal
Service principals provide a way for you to create non-interactive
accounts that you can use to manipulate resources. Service principals
are like user accounts to which you can apply rules using Azure Active
Directory. By granting the minimum permissions needed to a service
principal, you can ensure your automation scripts are even more
secure.
If you don't already have a service principal, create one.
Log in with the service principal:
Login-AzureRmAccount -ServicePrincipal -ApplicationId "http://my-app" -Credential $pscredential -TenantId $tenantid

Run BAT file as a Local User Account

I pulled this from another question, but I cannot seem to make this work.
I need to run this .bat file as a local admin account. I want users to be able to run and install this without having local admin rights.
I'm not sure what's wrong though.
$username = 'localadmin'
$password = 'passwordforlocaladmin'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process -Filepath "p:\kaceInstaller\kaceinstall3.bat" -Credential $credential
The error I'm getting back is:
Start-Process : This command cannot be executed due to the error: The directory
name is invalid.
At P:\kaceInstaller\misc\kaceSetup.ps1:7 char:14
+ Start-Process <<<< cmd -Credential $credential
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommandy
If you want to allow users to run something as a local administrator account without effectively giving them the password to the local admin account, I would suggest to create a scheduled task running as a local admin. Users can manually trigger that task, which will then be executed under the local admin account. Creating the task withoug saving the credentials should work, but even if you have to save the credentials they won't be accessible to your users.
For access to network shares you may need to connect/disconnect the share with explicit credentials from within the script that the scheduled task runs, though, because the local account usually doesn't have permission to access the network drives mapped by your domain user.
net use X: \\server\share\kaceInstaller password /user:DOMAIN\user
call X:\kaceinstall3.bat
net use X: /d
Make DOMAIN\user a dedicated account that has access only to \\server\share and nothing else to minimize risk.
Note that you must make sure that the script run by the task is not writable by regular users, otherwise they will be able to run arbitrary commands with admin privileges by simply modifying the script.

How to login from an Azure Resource Manager Runbook?

Using the new Azure portal, I am trying to add a powershell runbook that will start a specific VM. This is not something that will be run in powershell from my PC, it will instead run as an ARM job. I can't seem to find a way to successfully login.
If running from my desktop in powershell I can just call Login-AzureRmAccount and it will launch a login dialog before running any further steps. From what I've read on the web it seemed that what I needed to do was add a credential to my automation account, retrieve it and then call the same Login method. I've now done that, but still can't log in.
Import-Module AzureRM.Compute
$AutomationCredentialAssetName = "automation"
$Cred = Get-AutomationPSCredential -Name $AutomationCredentialAssetName
Write-Output $Cred
Login-AzureRmAccount -Credential $Cred
Start-AzureRmVm -Name 'myvmname' -ResourceGroupName 'myresourcegroupname'
The credential is being retrieved correctly (get's written to output) but the call to the Login-AzureRmAccount fails with:
Login-AzureRmAccount : unknown_user_type: Unknown User Type
At line:10 char:1
+ Login-AzureRmAccount -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Common.Authentication.AadAuthenticationFailedException,Microsoft.Azure.Com
mands.Profile.AddAzureRMAccountCommand
If I don't attempt to log in first I get a message telling me to call Login-AzureRmAccount first.
How do I authenticate from within a runbook so that I can run automation tasks? What am I doing wrong?
We have subsequently discovered the the automation account created a connection when created that can be used to login:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
At a guess you are trying to log in with a Microsoft account, which can only be done interactively (as it needs to redirect through live.com). You will need to create a user within the tenant (Active Directory) that you are authenticating against in order for non-interactive login to work.
The easiest method to make this work is to create an account in the old portal (the new portal doesn't support Active Directory management yet) and then to add that user as a co-administrator in settings > administrators.
You can create a user through Powershell, and assign much more granular permissions, but while you're working your way around things it is probably easier to stay within the portal.
There is no significant difference between a user created through the old portal and one created via AzureRm commands.
I just encountered the same problem and while the information posted here was helpful it didn't solve the problem completely.
The key insight I needed was that in order to use Azure Cmdlets one has to configure a 'Run as Account'. (See https://learn.microsoft.com/en-us/azure/automation/automation-sec-configure-azure-runas-account)
It can be set up under Account Settings section of the azure automation account.
Once you have the 'Run as Account' you can use the method proposed by BlackSpy to log in. Namely:
# Get the connection
$servicePrincipalConnection = Get-AutomationConnection -Name AzureRunAsConnection
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
Hope this might help someone.
The official advice is to use a ServicePrincipal for automation - you can either use Secret or Certificate credentials with a service principal, and certificates work the best.
It is still possible to use a work or school account for automated login (Login with just -Credential), but this requires that your organization does not require two-factor authentication. It is unfortunately not possible to use a Microsoft Account for this - microsoft accounts require user interaction for any login.

Add user to Azure AD from another Azure AD via powershell

In the Azure portal I can click Add User and select User in another Windows Azure AD directory to add a user from another directory to the current directory (As long as I have sufficient authorization in both directories).
I'd like to be able to do this via powershell, but it doesn't seem possible since you can only connect to a single directory.
Here's the scenario:
admin#tenant1.onmicrosoft.com is a global admin in both tenant1 and tenant2. In the portal, I can see and manage both directories while logged as admin#tenant1.onmicrosoft.com.
But in powershell, if I do:
$cred = Get-Credential -UserName admin#tenant1.onmicrosoft.com
Connect-MsolService -Credential $cred
I can only see and manage the tenant1 directory. So I tried this:
$cred = Get-Credential -UserName admin#tenant1.onmicrosoft.com
Connect-MsolService -Credential $cred
$user = Get-MsolUser -UserPrincipalName user#myfederateddomain.com
$cred2 = Get-Credential -UserName admin#tenant2.onmicrosoft.com
Connect-MsolService -Credential $cred2
$user | New-MsolUser
But this failed:
New-MsolUser : Unable to create this user because the user principal name provided is not on a verified domain.
At line:1 char:9
+ $user | New-MsolUser
+ ~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [New-MsolUser], MicrosoftOnlineException
+ FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.PropertyDomainValidationException,Microsoft.Online.Administ
ration.Automation.NewUser
I'm guessing this just isn't possible, but maybe someone can point out something I missed?
Unfortunately, as you had guessed, this functionality is not currently available through Azure AD PowerShell. It is something that we'd like to add in the future, but I don't have an exact timeframe for this yet.
UPDATE 4/14/2018: Sorry - was not monitoring this. There is now a way to invite a user from another tenant to the current tenant using Microsoft Graph. Please see https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/invitation. It still doesn't look like there's any Azure AD PowerShell for this.