AX 2012 R3 AIF System Services Callcontext of another user - c#

Is it possible to call the AIF system services using a callcontext of another user?
I specifically need to fetch which tables a user has access to. By using the method GetAccessRights in the UserSessionService, I can extract which tables I have access to.
I need to call this for other users, so I tried setting the CallContext.LogonAsUser to another user, but I get the error:
An unhandled exception of type 'System.ServiceModel.FaultException'
occurred in mscorlib.dll
Additional information: Failed to logon to Microsoft Dynamics AX.
To be able to use LogonAsUser on custom services, I need to set the "Trusted intermediary users" on the inbound port. However, it doesn't seem to be possible to set this on the system services.
I'm testing this on a contoso image. I'm logged in as contoso\Administrator.
The complete code:
USSReference.UserSessionServiceClient client = new USSReference.UserSessionServiceClient();
USSReference.CallContext context = new USSReference.CallContext
{
LogonAsUser = "VishwaR"
};
USSReference.AccessControlledItemKey key = new USSReference.AccessControlledItemKey();
key.ItemType = USSReference.AccessControlledType.Table;
key.ItemName = "CUSTTABLE";
UserService.USSReference.AccessRight[] rights = client.GetAccessRights(context, new USSReference.AccessControlledItemKey[] { key });

You can create custom AIF Inbound Port and add AifUserSessionService.GetAccessRights operation.
Here you can set Allow trusted intermediary to impersonate.

Related

How can we access the exchange mailboxes via EWS when the user has no own mailbox?

We want to access mailboxes via EWS (Exchange Web Services) with an dedicated user who has no own mailbox.
The target is to cover all Exchange Server version 2007-2019.
Reason why we want to have an dedicated user with no mailbox: We want analyze all mailboxes in an Exchange Server by an software. But therefore we not really need an user and even an mailbox. Only the data inside the mailboxes are interesting for the software.
We use Independentsoft´s API to access the EWS:
var lCredential = new NetworkCredential("ADUserWithNoMailbox", "Password");
m_Service = new Service("https://hostname/EWS/Exchange.asmx", lCredential);
try
{
FindFolderResponse lResponse = m_Service.FindFolder(StandardFolder.MailboxRoot);
// [...]
}
catch (Exception e)
{
// cast in into multiple expected types
var lServiceRequestException = e as Independentsoft.Exchange.ServiceRequestException;
if (lServiceRequestException.ResponseCode == "ErrorNonExistentMailbox")
{
// lServiceRequestException.Message shows: "No mailbox with such guid."
// [...]
}
// [...]
throw;
}
Our user ADUserWithNoMailbox which is in the Active Directory has no mailbox. Therefore an exception occurs with the message:
"No mailbox with such guid."
Question: How can we access the exchange mailboxes via EWS when the user has no own mailbox?
It should work okay if the servers are patched to the correct levels eg there can be problem like https://support.microsoft.com/en-us/topic/-the-smtp-address-has-no-mailbox-associated-with-it-error-when-you-access-a-user-s-mailbox-by-using-ews-application-c8e31e36-b6e2-229e-cc78-305ab9fea94a. I've always found this to be problematic if your deploying apps in different customer environments and found for most OnPrem deployments giving the Service account your using a Mailbox is not a problem, to stop it appearing in address lists most customers can just hide it. (Office365 is a different matter because of the cost of consuming a licence but you can use App tokens which don't require a user or mailbox)
Probably for your requirement using EWS Impersonation https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/impersonation-and-ews-in-exchange is a better option as that will give you access to all Mailboxes.

The LDAP Server is Unavailable using PrincipalContext and ADLDS

We are making use of ADLDS for our user management and authentication. We can successfully query the instance without problems. However, trying to perform an operation such as SetPassword will fail or even trying to create a new user if a password is not set, it fails. I can successfully update a user as long as its not password I'm trying to update. I've been reading a lot of different articles relating to this but not finding a resolution. Posting to see if I can get some fresh perspective on this issue, thanks for any input.
EXAMPLE
ContextType ctxType = ContextType.ApplicationDirectory;
string server = "myadldsserver.com";
string usersCN = "CN=Users,..."; // container where users reside
ContextOptions ctxOpts = ContextOptions.SimpleBind;
string uname = "myuser";
string pswrd = "mypass";
using(var ctx = new PrincipalContext(ctxType, server, usersCN, ctxOpts, uname, pswrd)
using(var newUser = new UserPrincipal(ctx)) {
newUser.Name = "newusername";
newUser.Enabled = true;
newUser.UserPrincipalName = "newusername";
newUser.Save();
newUser.SetPassword("newuserpassword");
}
ERROR 1
The first problem I encounter if I try to create a new UserPrincipal and call Save without having set the password like in Example above I get the exception A constraint violation occurred. with an InnerException extend message of 0000052D: AtrErr: DSID-033807D7, #1:0: 0000052D: DSID-033807D7, problem 1005 (CONSTRAINT_ATT_TYPE), data 2246, Att 9005a (unicodePwd)
Because of this error I tried moving the SetPassword before calling Save along with other approaches I found online such as getting the DirectoryEntry from the UserPrincipal and trying to call SetPassword but got a different error.
ERROR 2
Calling SetPassword before calling UserPrincipal.Save, when save is called, results in the error The directory property cannot be found in the cache.
Note that the same error will occur if I trying calling ResetPassword or getting a DirectoryEntry and calling Invoke("SetPassword"... as well
ERROR 3
From my research most seem to indicate this could have to do with needing to access AD LDS using a Secure connection. So, I changed my server to include the port of 636 string server = "myadldsserver.com:636" and I changed the ContextOptions to be ContextOptions.SimpleBind | ContextOptions.SecureSocketLayer.
Making these changes when the PrincipalContext is being constructed I get the following exception The server could not be contacted. with an inner exception of The LDAP server is unavailable., HResult is -2146233087
JAVA and LDP
To add some background to this, we do have similar code written in an older Java application. We are trying to port some of this logic over to .NET side in C#. The code in Java makes use of a Java keystore that contains the certificate that was generated on the AD LDS server. The Java application of course has no issues using the SSL port. We know the server seems to be configured correctly, it's just an issue of how to access it from .NET side.
Is there an equivalent on the .NET side such as the keystore in Java? We know that an SSL connection can be made to server. We have verified this using LDP as well.
GOALS
Be able to create a new user and set their password during creation
Be able to ResetPassword or ChangePassword for a user
Connect to our AD LDS instance from .NET securely
Have you tried using Microsoft Management Console to import the certificate?
Two ways to install the certificate
Either
Open a cmd.exe console and type "MMC"
File > Add/Remove Snap-In...
Select Certificates, click Add
Choose Computer Account and Local Computer when prompted, then OK...
Certificates should now be showing under Console Root
Certificates > Trusted Root Certification Authorities > Certificates > (right-click) > All Tasks > Import Certificate...
Find the certificate you want to import, click Next and choose defaults (Trusted Root Certification Authorities should already be
selected)
Click Next, Finish
(or)
Simply double-click on the .cer file for the certificate in Windows
Explorer, click Install Certificate... > Next > select the option to
"Place all certificates in following store" > Browse... > Select
Trusted Root Certification Authorities. Continue with next until done.
At this point your certificate is installed, and you should be able to communicate securely with your ADLDS server.

Accessing MongoDB from a SQL Server 2008 CLR trigger

I'm using a SQL CLR trigger to push updates from the relational DB to a MongoDB instance. Both databases are running on the same Windows 2012 machine.
My SQL CLR project is built on .NET 3.5 and is using the mongocsharpdriver 1.10.0.
The C# code within my trigger is as follows:
SqlPipe pipe = SqlContext.Pipe;
pipe.Send("Begin ReportUpdateTrigger.VTProperty");
try
{
var settings = new MongoClientSettings();
settings.Server = new MongoServerAddress("127.0.0.1", 27017);
var client = new MongoClient(settings);
var server = client.GetServer();
var db = server.GetDatabase("VTProperty");
var coll = db.GetCollection<object>("Property");
var item = new { name = "test", datecreated = DateTime.Now };
coll.Insert(item);
}
catch (Exception ex)
{
pipe.Send("Error sending update to Reporting database: " + ex.Message);
}
pipe.Send("Done ReportUpdateTrigger.VTProperty");
(this is test code just to verify that the MongoDB operation will work).
I run the exact same code from a separate console app, and the data is posted to Mongo with no problems.
When running from the trigger, I see the following error:
Begin ReportUpdateTrigger.VTProperty Error sending update to Reporting
database: Unable to connect to server 127.0.0.1:27017: The type
initializer for 'MongoDB.Bson.Serialization.BsonSerializer' threw an
exception.. Done ReportUpdateTrigger.VTProperty
I have my DLL (and all supporting DLLs, including the MongoDB drivers) referenced as assemblies within the DB server. CLR is enabled. I know that the trigger is executing because I am getting the custom status and error messages in the SQL output window.
My hunch is that whatever user/process is executing the trigger code does not have access to the Mongo instance. Hence the "Unable to connect to server 127.0.0.1:27017" error. Not sure what my next step should be.
By default, SQLCLR external access has a security context of the service account (i.e. "Logon As" account) of the MSSQLSERVER service (or MSSQL$InstanceName, or something like that). And that service account, by default, is the Local System account. You can do one of two things here:
If your MSSQLSERVER service is using "Local System" as the account, then create a real local or domain / AD account and make that the service account. Then just make sure that the new real account has access to MongoDB.
Regardless of anything else, it is often best to have services such as SQL Server uses their own service accounts. That makes it easier to control and confine the permssions.
If you are using Windows logins, then you have the option of enabling Impersonation in the .NET code. When using Impersonation, the security context of external calls is set to the Windows Login that is executing the SQLCLR object.
For this, you would need to add something like the following to your code:
using System.Security.Principal;
// above the "try" block
WindowsImpersonationContext _ImpersonationIdentity = null;
// inside the "try", before anything else
_ImpersonationIdentity = SqlContext.WindowsIdentity.Impersonate();
// in a "finally" block
if (_ImpersonationIdentity != null)
{
_ImpersonationIdentity.Undo();
}

StreamInsight: Access is denied

I hosted a StreamInsight server to windows service. The windows service run with LocalSystem.
In OnNext() method, I have code access to server
using (
var server =
Server.Connect(
new EndpointAddress(#StreamInsightConfiguration.Default.StreamInsightServiceHostURL))
)
{
var application = server.Applications[StreamInsightConfiguration.Default.StreamInsightApplicationName];
return application;
}
At line server.Applications[StreamInsightConfiguration.Default.StreamInsightApplicationName]; I received a message Access is denied.
I also add NT\SYSTEM to StreamInsightUsers$Default group.
How to fix this problem ?
If a user is logged in while the account is being added to the group, the user must log off and then log on again in order for the group membership to become effective. Users that are not members of this group will receive "access denied" errors when attempting to connect to the server’s Web service endpoint in the Event Flow Debugger and other client programs.
Courtesy:- https://msdn.microsoft.com/en-us/library/ee378749(v=sql.111).aspx

Check if an Azure VM is running

I want to query an existing azure virtual machine to check whether it is fully deployed and able to be connected to remotely. Is there any way to do this using the Azure Rest API?
I've outlined my current process and why I desire such a call below.
I am using the Windows Azure management library to create a VM using ComputeManagementClient and the CreateDeploymentAsync function. This then returns a status of Succeeded, if I then do a get on the deployment it has a status of DeploymentStatus.Running.
After this has run I am trying to create a remote powershell connection so I can format the disk. I keep getting an error on this as it is unable to create the session.
WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. For more information, see the about_Remote_Troubleshooting Help topic.
If I go to the azure management portal the status is provisioning, I assume this is why i cannot create a session.
Process
CreateAzureVM()
CheckAzureVmCanBeConnectedTo() //I am unable to do this correctly
RunPowershellScriptOnVM() // this fails
You should be able to use Get Deployment to poll for the role's InstanceStatus (note that InstanceStatus != Status). When the InstanceStatus is ReadyRole, you should be able to log into your machine.
There's a distinction between a Deployment status and a Role InstanceStatus. Think of the role as an actual virtual machine, whereas a Deployment may describe multiple VMs.
SubscriptionCloudCredentials certificate = new CertificateCloudCredentials(subscriptionId, x509Certificate);
IComputeManagementClient ComputeManagementClient = new ComputeManagementClient(certificate);
var deployments = ComputeManagementClient.Deployments.GetBySlot(hostedServiceName, DeploymentSlot.YourDeploymentSlot);
var state = deployments.RoleInstances.First().PowerState;
I hope that this will help you.
Without seeing your code it's hard to say exactly what you need to do but I would recommend that you utilise the await keyword to wait for the completion of the call to the Azure API to create the VM. See the code samples under "Deploy a Virtual Machine" in this MSDN guide: http://msdn.microsoft.com/en-us/library/azure/dn722415.aspx#bk_createres

Categories

Resources