I am trying to execute Add-Mailboxpermission from a ASPX page with impersonation of a specific user. an application error from MSExchange Common source is logged in the Event viewer of the web server.
Watson report about to be sent to dw20.exe for process id: 2992, with parameters: E12, c-buddy-RTL-AMD64, 08.03.0083.006, w3wp, M.E.D.Directory, M.E.D.D.ConnectionPoolManager.BlockImpersonatedCallers, M.E.Common.FailFastException, c84f, 08.03.0213.000. ErrorReportingEnabled: False
The same code for executing a different Exchange CMDlets including the impersonation call is used and completes without any error.
String ErrorText = "";
RunspaceConfiguration config = RunspaceConfiguration.Create();
PSSnapInException warning;
sDecryptedPwd = SecurityManager.Decrypt(AdminPassword, true);
using (new Impersonator(AdminUserName, "domain name", sDecryptedPwd))
{
// Load Exchange PowerShell snap-in.
config.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out warning);
if (warning != null)
throw warning;
using (Runspace thisRunspace = RunspaceFactory.CreateRunspace(config))
{
try
{
thisRunspace.Open();
using (Pipeline thisPipeline = thisRunspace.CreatePipeline())
{
//Please change parameter values.
thisPipeline.Commands.Add("Add-MailboxPermission");
thisPipeline.Commands[0].Parameters.Add("Identity", sMailboxName);
thisPipeline.Commands[0].Parameters.Add("User", sUserName);
thisPipeline.Commands[0].Parameters.Add("AccessRights", sAccessRights);
thisPipeline.Commands[0].Parameters.Add("DomainController", sDomainController);
iLogManager.Info("Identity: " + sMailboxName + " User: " + sUserName + " AccessRights: " + sAccessRights + " DomainController: " + sDomainController);
try
{
thisPipeline.Invoke();
iLogManager.Info(thisPipeline.Commands[0].CommandText);
}
catch (Exception ex)
{
ErrorText = "Error: " + ex.ToString();
}
// Check for errors in the pipeline and throw an exception if necessary.
if (thisPipeline.Error != null && thisPipeline.Error.Count > 0)
{
StringBuilder pipelineError = new StringBuilder();
pipelineError.AppendFormat("Error calling Add-MailboxPermission.");
foreach (object item in thisPipeline.Error.ReadToEnd())
{
pipelineError.AppendFormat("{0}\n", item.ToString());
}
ErrorText = ErrorText + "Error: " + pipelineError.ToString() + Environment.NewLine;
}
}
}
finally
{
thisRunspace.Close();
}
}
}
if (ErrorText == "")
return "no error occurred.";
else
return ErrorText;
Does Exchange allows impersonation of Exchange CMDlets that modifies ACL's or am I doing something wrong here..
Can anybody help me here, there is not much information about Exchange Powershell CMdlets with impersonation from ASPX page.
Related
I am working on an application that connects to Dynamics 365 and creates contacts there, for example.
My question now is how to configure the login.
For testing, multi-factor authentication is disabled and it works so far. However, in the production system, MFA will be active.
I want to avoid users using an app password.
Is there a way to pop up the standard O365 login popup window from within a WinForms application?
Unfortunately I couldn't find anything about it.
What would make the most sense here?
Thats my code so far:
public CrmServiceClient connect_crm()
{
string ConnectionString = "AuthType = OAuth; " +
"Username= " + textBox1.Text + ";" +
"Password=" + textBox2.Text + ";" +
"Url=https://company.dynamics.com;" +
"RedirectUri=app://;" +
"AppId=XXXXXXXX-XXXXX-XXXX-XXXX-XXXXXXXXXXXXX;" +
"LoginPrompt=Auto";
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
svc = new CrmServiceClient(ConnectionString);
try
{
if (svc != null && svc.IsReady)
{
label4.BackColor = Color.LightGreen;
label4.Text = "Connected";
CreateContact2(svc);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return svc;
}
I've got the solution!
You need to use the client secret from the app, you registered in azure.
And you have to create an application user in dynamics. (via power platform admin ceter)
See here: https://softchief.com/2021/08/03/connect-dynamics-365-from-console-c-application-in-mfa-enabled-access-using-client-secret-and-azure-client-id/
public CrmServiceClient connect_crm()
{
string ConnectionString = "AuthType = ClientSecret; " +
"Url=https://company.dynamics.com;" +
"ClientId=XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX;" + //AppID
"ClientSecret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //ClientKey
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
svc = new CrmServiceClient(ConnectionString);
try
{
if (svc != null && svc.IsReady)
{
label4.BackColor = Color.LightGreen;
label4.Text = "Connected!";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return svc;
}
I am attempting to have specific event logs that contain a username that are Security Audit Failures from a DC, in powershell I can easily do this with something like this:
Where the variables would be something like: $DC = "MyDomainController" and $user = "jdoe"
Get-WinEvent -ComputerName $DC -FilterHashtable #{Logname='Security';Keywords='4503599627370496';Data=$user} -MaxEvents 4 | Format-List -Property ID, TimeCreated, MachineName, Message
This would pull 4 event logs that are security audit failures with the person's username from a DC I am looking at, however I have been unable to find or reproduce this behavior to something similar in vb.net, I have been searching pages for the last few days and coming up with a lot of writing and pulling all logs on DC's but not filtering down, any help or guidance would be great, thank you!
I was able to find the answer to this by looking at custom log query's by using xpath, I did the following in C# but the same can be applied in VB, Domaincontroller.text = The domain controller your looking up: Username.text = The AD username to lookup Statustextbox = I have all the logs go to a textbox to read but you could do something like console.writeline
private void LookupLogs_Click(object sender, EventArgs e)
{
Statustextbox.Clear();
string query = "<QueryList>" +
" <Query Id=\"0\" Path=\"Security\">" +
" <Select Path=\"Security\">" +
" *[System[band(Keywords,4503599627370496)]] and *[EventData[Data[#Name='TargetUserName'] and (Data='" + Username.Text + "')]]" +
" </Select>" +
" </Query>" +
"</QueryList>";
EventLogSession session = new EventLogSession(DomainController.Text);
EventLogQuery evntquery = new EventLogQuery("Security", PathType.LogName, query);
evntquery.Session = session;
try
{
EventLogReader logreader = new EventLogReader(evntquery);
DisplayEventAndLogInformation(logreader);
}
catch (Exception ex)
{
MessageBox.Show("An exception occured: " + ex.Message);
}
}
private void DisplayEventAndLogInformation(EventLogReader logReader)
{
for (EventRecord eventInstance = logReader.ReadEvent();
null != eventInstance; eventInstance = logReader.ReadEvent())
{
Statustextbox.AppendText(Environment.NewLine + Environment.NewLine);
Statustextbox.AppendText("---------------------------------------------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine);
Statustextbox.AppendText("Event ID: " + eventInstance.Id + Environment.NewLine);
Statustextbox.AppendText("Publisher: " + eventInstance.ProviderName + Environment.NewLine);
try
{
Statustextbox.AppendText("Description: " + eventInstance.FormatDescription() + Environment.NewLine);
}
catch (EventLogException ex)
{
Statustextbox.AppendText("An exception was thrown: " + ex.Message + Environment.NewLine);
}
EventLogRecord logRecord = (EventLogRecord)eventInstance;
Statustextbox.AppendText(Environment.NewLine);
Statustextbox.AppendText("Container Event Log: " + logRecord.ContainerLog + Environment.NewLine);
}
}
I am trying to execute a piece of Azure script to check if the user object is synced from on-prem AD to Azure as below.
username follows the pattern of a UPN. example: john.Smith#ed.com
//Check Azure to see if user is synced to office 365
private static bool IsAccountSyncedToOffice365(string username)
{
StringBuilder cmd = CreateAzureConnectScript();
//cmd.AppendLine("Get-MsolUser -UserPrincipalName " + username + " -ErrorAction SilentlyContinue");
cmd.AppendLine("$global:res = \"false\"");
cmd.AppendLine("$global:user = \"false\"");
cmd.AppendLine("try{ if(($global:user=Get-MsolUser -UserPrincipalName " + username + " -ErrorAction Stop).ImmutableId -ne $null) { $global:res = \"true\"} } Catch { $global:errorMessage = $_.Exception.Message}");
try
{
Collection<PSObject> results;
string output, error, errorMessageAzureCnn = "";
do
{
results = null;
output = "";
error = "";
var rs = CreateAzureRunspace();
var pipe = rs.CreatePipeline();
pipe.Commands.AddScript(cmd.ToString());
results = pipe.Invoke();
output = (rs.SessionStateProxy.PSVariable.GetValue("res")) != null ? rs.SessionStateProxy.PSVariable.GetValue("res").ToString() : "false";
error = (rs.SessionStateProxy.PSVariable.GetValue("errorMessage")) != null ? rs.SessionStateProxy.PSVariable.GetValue("errorMessage").ToString() : "null";
errorMessageAzureCnn = (rs.SessionStateProxy.PSVariable.GetValue("errorMessageAzureCnn")) != null ? rs.SessionStateProxy.PSVariable.GetValue("errorMessageAzureCnn").ToString() : "null";
ExceptionManager.Publish(new Exception("LOG: Queried Azure at:" + DateTime.Now + " for user:" + username + " Result: " + output + " Error: " + error + " errorMessageAzureCnn: " + errorMessageAzureCnn));
Thread.Sleep(60000); //sleep for 60 seconds
pipe.Dispose();
rs.Close();
rs.Dispose();
} while (output.Trim().ToLower() != "true");
ExceptionManager.Publish(new Exception("LOG: " + username + " is found synced to Azure at: " + DateTime.Now));
cmd.Clear();
return true;
}
catch (Exception ex)
{
ExceptionManager.Publish(new Exception("Error checking Azure to see if the user is synced to office 365 or not.. " + ex.Message));
throw ex;
}
}
private static StringBuilder CreateAzureConnectScript()
{
StringBuilder ss = new StringBuilder();
MSCredential cred = new MSCredential();
var username = cred.username;
var pwd = cred.password;
try
{
ss.AppendLine("try {");
ss.AppendLine("$password = ConvertTo-SecureString \"" + pwd + "\" -AsPlainText –Force");
ss.AppendLine("$credential = New-Object System.Management.Automation.PsCredential(\"" + username + "\",$password)");
ss.AppendLine("$cred = Get-Credential -cred $credential");
ss.AppendLine("Import-Module MSOnline");
ss.AppendLine("Start-Sleep -s 10");
ss.AppendLine("Connect-Msolservice -cred $cred");
ss.AppendLine("} Catch { $global:errorMessageAzureCnn = $_.Exception.Message }");
//ExceptionManager.Publish(new Exception("LOG:pwd: " + pwd + " uname:" + username));
return ss;
}
catch (Exception ex)
{
ExceptionManager.Publish(new Exception("Error enabling the remote mailbox.. " + ex.Message));
throw ex;
}
}
While the script executes successfully through Powershell Window on the same server having got all the latest versions of the modules installed. When trying to execute the same command from C# code it throws the below exception collected from the powershell exception handling $global:errorMessage = $_.Exception.Message.
Show Details Exception (0): [] LOG: Queried Azure at:7/30/2015 12:00:55 PM for user:testuser0385#xxx.com Result: false Error: You must call the Connect-MsolService cmdlet before calling any other cmdlets. errorMessageAzureCnn: null
Worth mentioning that I have got the same code as below working in one server but it is throwing the below error on a production server (Windows Server 2008 R2 Datacenter) and only via the code it is happening. via the powershell window it works perfectly fine.
Good to know your thoughts about what looks wrong or needed to be looked into.
Thanks!
It suggests that the sign in is failing, but you're pushing on with the Get-MsolUser anyway. The Connect-MsolService cmdlet fails if it cannot communicate to the Microsoft Online Services Sign-In Assistant. Ref: https://community.office365.com/en-us/f/156/t/252201
Has the production server got all the pre-requisites installed: Microsoft Online Services Sign-In Assistant and .NET 3.5? We had a problem in production (Azure PAAS) where the guest OS image was automatically updated and was missing .NET 3.5, which broke our Azure AD PowerShell processes.
I am trying to connect to my companies Exchange 2003 server using RDO & MAPI which I've never done before. I have found a pretty good site that uses Outlook's Redemption (http://www.dimastr.com/redemption/home.htm) but with all of the examples on the site using VB.NET and me not being great at programming it's a bit difficult to get this working.
So far I have this code
static void ConnectToExchange()
{
object oItems;
//string outLookUser = "My Profile Name";
string outLookUser = "username#xxx.xxxx";
string ToEmailAddress = "username#xxxx.com";
string FromEmailAddress = "username#xxx.com";
string outLookServer = "xxservernamexx";
string sMessageBody =
"\n outLookUser: " + outLookUser +
"\n outLookServer: " + outLookServer +
"\n\n";
RDOSession Session = new RDOSession();
try
{
Session.LogonExchangeMailbox(outLookUser,outLookServer);
int mailboxCount = Session.Stores.Count;
string defaultStore = Session.Stores.DefaultStore.Name;
RDOFolder TestTaxCert = Session.GetFolderFromPath(#"\\Public Folders\All Public Folders\TestTaxCert");
}
catch (Exception ex)
{
Session = null;
//System.Web.Mail.SmtpMail.Send(ToEmailAddress, FromEmailAddress, "Error", sMessageBody + " " + ex.Message);
}
finally
{
if ((Session != null))
{
if (Session.LoggedOn)
{
Session.Logoff();
}
}
}
}
}
My problem is that once the program hits the Session.LogonExchangeMailbox(outLookUser,outLookServer); line, a prompt appears asking for my credentials (username, domain, password) and no matter what information I fed the prompt it denied permission.
SO if someone can help me with that and then also with connecting to the public folders...that'd be greaaat
Make sure your code is running as the domain user specified in the call to LogonExchangeMailbox.
Did you really mean 2003, or is it Exchange 2013?
I'm using Redemption dll (http://www.dimastr.com/redemption/) and I've created an exe that accesses my mail box.
I run the exe in Windows Scheduler under my username and it works fine, I get an email sent to me (see below code).
When I change the runas username in Scheduler to someone else and try to access their mail box Profile I get an error. System.IO.FileLoadException
static void Main(string[] args)
{
System.Diagnostics.Debugger.Break();
object oItems;
//string outLookUser = "My Profile Name";
string outLookUser = "Other User Profile Name";
string ToEmailAddress = "abc.email#xyz.com";
string FromEmailAddress = "abc.email#xyz.com";
string outLookServer = "exchangeServer.com";
string sMessageBody =
"\n outLookUser: " + outLookUser +
"\n outLookServer: " + outLookServer +
"\n\n";
RDOSession Session = null;
try
{
rdoDefaultFolders olFolderInbox = rdoDefaultFolders.olFolderInbox;
Session = new RDOSession();
RDOFolder objFolder;
Session.LogonExchangeMailbox(outLookUser, outLookServer);
int mailboxCount = Session.Stores.Count;
string defaultStore = Session.Stores.DefaultStore.Name;
sMessageBody +=
"\n mailboxCount: " + mailboxCount.ToString() +
"\n defaultStore: " + defaultStore +
"\n\n";
//RDOStore rmpMetering = Session.Stores.GetSharedMailbox("Name of another mailbox");
//objFolder = rmpMetering.GetDefaultFolder(olFolderInbox);
objFolder = Session.GetDefaultFolder(olFolderInbox);
oItems = objFolder.Items;
int totalcount = objFolder.Items.Count;
if (totalcount > 10) totalcount = 10;
for (int loopcounter = 1; loopcounter < totalcount; loopcounter++)
{
RDOMail oItem = objFolder.Items[loopcounter];
string attachmentName = string.Empty;
foreach (RDOAttachment attachment in oItem.Attachments)
{
attachmentName += attachment.FileName + " ";
if (attachmentName.Trim() == "Data.csv")
{
attachment.SaveAsFile(#"C:\datafiles\" + attachmentName.Trim());
foreach (RDOFolder archiveFolder in objFolder.Folders)
{
if (archiveFolder.Name == "DataFileArchive")
{
oItem.MarkRead(true);
oItem.Move(archiveFolder);
}
}
}
}
sMessageBody += oItem.Subject + " " + attachmentName + "\n";
if ((oItem.UnRead))
{
//Do whatever you need this for
//sMessageBody = oItem.Body;
//oItem.MarkRead(true);
}
}
System.Web.Mail.SmtpMail.Send(ToEmailAddress,FromEmailAddress
, "Data File Processing-" + DateTime.Now.ToString()
,"" + sMessageBody);
}
catch (Exception ex)
{
Session = null;
System.Web.Mail.SmtpMail.Send(ToEmailAddress, FromEmailAddress, "Error", sMessageBody + " " + ex.Message);
}
finally
{
if ((Session != null))
{
if (Session.LoggedOn)
{
Session.Logoff();
}
}
}
}
When I try to run the same exe on another machine with me logged in I get this error,
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or ass
embly 'Interop.Redemption, Version=4.7.0.0, Culture=neutral, PublicKeyToken=null
' or one of its dependencies. The system cannot find the file specified.
File name: 'Interop.Redemption, Version=4.7.0.0, Culture=neutral, PublicKeyToken
=null'
at RPMDataFileProcessing.Program.Main(String[] args)
Has anyone got any ideas on what I'm doing wrong, can Redemption be used in this way?
I got this working in the end by ensuring that the user you are logged in as, has 'full mailbox rights' to the mail box you are trying to see.