Wednesday, December 23, 2015

Security for all is good

It's been discovered that Juniper Networks has been using a flawed encryption for years.  Possibly a result of NSA and/or a bug.  When it becomes easy for good guys to decrypt information for the sake of national security, it makes it just as easy for bad guys to decrypt.  Engineering secure systems without backdoors works for everybody.

Juniper backdoor

Monday, December 14, 2015

MIM 2016 and Exchange 2010: no-start-ma during AD export

I've recently been playing around with MIM 2016 and stood up an Exchange 2010 server within the environment.  Trying to provision to AD with Exchange functionality has proven difficult.  I would get no-start-ma in the MIM Sync console after the AD export.

When I removed the removed the exchange provisioning functionality in the MA extensions section, the export worked as expected. I was able to prove that I could connect to remote powershell so that didn't seem to be the issue yet I continue having the problem.  After googling around I ran across Thomas' blog in setspn.blogspot and found the same thing.

On the MIM sync server, install .Net 4.6.  Install all windows updates (including optional).  Reboot - I had to reboot twice as the FIM service wouldn't start the first time.  All seems to be working now.  Thanks for the info Thomas.

Monday, March 9, 2015

Updating Workday using .NET

The second post here will give you a good start how to update a user who's in Workday.  The community had zero examples how to do this, so you should find this helpful.

Read the earlier post regarding pre-reqs needed to connect to Workday using .NET.  This time I'll do it in VB.NET and the below code will update the email address.


  empId = "12345"
                workerType = "Employee_ID"

                Dim emailValue As String = ""
                Dim effectiveDate As Date = Now()

                Dim emailRequest As New Maintain_Contact_Information_for_Person_Event_RequestType()
                emailRequest.version = "v22.0"
                emailRequest.Add_Only = True

                emailRequest.Maintain_Contact_Information_Data = New Contact_Information_for_Person_Event_DataType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data = New Contact_Information_DataType()

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data = New Email_Address_Information_DataType(0) {New Email_Address_Information_DataType()}

                emailRequest.Maintain_Contact_Information_Data.Worker_Reference = New WorkerObjectType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID = New WorkerObjectIDType(0) {New WorkerObjectIDType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).type = workerType
                emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).Value = empId

                emailRequest.Maintain_Contact_Information_Data.Effective_Date = effectiveDate
                emailRequest.Maintain_Contact_Information_Data.Effective_DateSpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Email_Address = emailValue
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data = New Communication_Method_Usage_Information_DataType(0) {New Communication_Method_Usage_Information_DataType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).[Public] = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).PublicSpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data = New Communication_Usage_Type_DataType(0) {New Communication_Usage_Type_DataType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Primary = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).PrimarySpecified = True

                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference = New Communication_Usage_TypeObjectType()
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID = New Communication_Usage_TypeObjectIDType(0) {New Communication_Usage_TypeObjectIDType()}
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID(0).type = "Communication_Usage_Type_ID"
                emailRequest.Maintain_Contact_Information_Data.Worker_Contact_Information_Data.Email_Address_Data(0).Usage_Data(0).Type_Data(0).Type_Reference.ID(0).Value = "WORK"

                Dim emailProxy As Human_ResourcesPortClient = CreateHumanResourcesProxy()

                Dim emailResponse As Maintain_Contact_Information_for_Person_Event_ResponseType

                    emailResponse = emailProxy.Maintain_Contact_Information(emailRequest)
                    Console.WriteLine("email update done")
                Catch fe As FaultException
                    If fe.Message.Contains("Invalid ID value.") Then
                            Console.WriteLine("Email Update ERROR as Employee will try CW")
                            emailRequest.Maintain_Contact_Information_Data.Worker_Reference.ID(0).type = "Contingent_Worker_ID"
                            emailResponse = emailProxy.Maintain_Contact_Information(emailRequest)
                            Console.WriteLine("email update done")
                        Catch ex As Exception
                            Console.WriteLine("Email Update ERROR as CW also " + fe.Message)
                        End Try

                    End If
                    'Console.WriteLine("Email Update ERROR " + fe.Message)
                End Try


Notice that in the Try/Catch section, I catch in case the update doesn't work as an Employee then I try again as a Contingent Worker.

The CreateHumanResourcesProxy function can be found in the earlier post.

Reading from Workday using .NET

Workday is a huge HR service and many companies are moving. Trying to figure out how to interact with Workday has been difficult. Mostly because there are so few samples available.  Workday has lots of documentation on their API, but because the objects are nested/nested/nested, it make it convoluted to figure out exactly where you need to go.

So here I'm putting out how to read a user from the Human Resources WSDL.

Before you can actually get this code to work you have to create reference file using svcutil then modify it because it creates 2 and 3 dimensional arrays.  This is a problem with Visual Studio.
See here for the pre-reqs and how to fix the Human_Resources.cs file

   empId = "12345";

                    var request = new Get_Workers_RequestType { version = "v22.0" };
                    var workerId = new WorkerObjectIDType()
                        type = "Employee_ID",
                        Value = empId

                    var idTypes = new List { workerId };
                    request.Request_References = new Worker_Request_ReferencesType { Worker_Reference = new WorkerObjectType[1] { new WorkerObjectType() } };                  
                    request.Request_References.Worker_Reference[0].ID = idTypes.ToArray();
                    request.Request_Criteria = new Worker_Request_CriteriaType
                        Exclude_Inactive_Workers = true,
                        Exclude_Inactive_WorkersSpecified = true

                    var proxy =  CreateHumanResourcesProxy();

                    Get_Workers_ResponseType response = null;
                        response = proxy.Get_Workers(request);
                        string first = response.Response_Data.FirstOrDefault().Worker_Data.Personal_Data.Name_Data.Preferred_Name_Data.Name_Detail_Data.First_Name;
                        string last = response.Response_Data.FirstOrDefault().Worker_Data.Personal_Data.Name_Data.Preferred_Name_Data.Name_Detail_Data.Last_Name;
                        Console.WriteLine(first + " " + last);
                    catch (FaultException fe)
                        // _logger.LogError("Error occurred invoking GetWorker", fe);
                        //return null;
                        Console.WriteLine("error " + fe.Message);

 public static Human_ResourcesPortClient CreateHumanResourcesProxy()
            SecurityBindingElement sb = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
            sb.IncludeTimestamp = false;
            const int lim = Int32.MaxValue;
            var timeout = TimeSpan.FromMinutes(2);

            var cb = new CustomBinding(
                new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
                    ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas
                        MaxDepth = lim,
                        MaxStringContentLength = lim,
                        MaxArrayLength = lim,
                        MaxBytesPerRead = lim,
                        MaxNameTableCharCount = lim
                new HttpsTransportBindingElement
                    MaxBufferPoolSize = lim,
                    MaxReceivedMessageSize = lim,
                    MaxBufferSize = lim,
                    Realm = string.Empty
                SendTimeout = timeout,
                ReceiveTimeout = timeout

            var proxy = new Human_ResourcesPortClient(cb, new EndpointAddress(""));

            proxy.ClientCredentials.UserName.UserName = "userName@tenant";
            proxy.ClientCredentials.UserName.Password = "pass";
            return proxy;


Keep in mind this will work with a worktype of Employee.  You have to change a few things for a Contingent Worker.

Saturday, January 10, 2015

The Project Journey

As a consultant we try very hard to help set the right expectations of how a project may go.  The client and typically us (the consultant) have an undue optimism of trajectory of a project.  Together we typically fool ourselves into thinking the project will go as expected, so as we estimate the project we try to hard to paint a rosy picture.  That nothing could ever go wrong.  Wrong.... 

The longer I do projects the more I try to estimate the way projects typically go.  There is always going to be something that you didn't expect.  Maybe a requirement was tougher than you expected, maybe the client forgot to mention something, maybe the requirements change.  The piece you are depending on to complete a milestone in the project is late.  There are a million things are might happen.  Things never go as expected. 

As consultants we try to 'be nice' to the client, don't want to scare them, try to be their friend.  You want to be their friend, then be honest and help guide them to the end of their journey.  Most of the time its not easy, but that's our job.  So accept it and try to enjoy the journey!  I borrowed this from a friend's Facebook post. A picture says a million words.