Community forum

Please note that VisualCron support is not actively monitoring this community forum. Please use our contact page for contacting the VisualCron support directly.


ROBV8R
2017-05-07T18:59:55Z
We use Group Managed Service Accounts (gMSA) when we can. They have several advantages over normal User Accounts used as Service Accounts. Primarily, no one knows the password (except the server and the Domain Controllers.) Secondarily, the password is changed at a pseudo-random internal by Active Directory.

It would be nice to use store gMSA's as a credential type in VisualCron.
Sponsor
Forum information
ROBV8R
2017-06-12T20:59:18Z
No one has replied. Has anyone had a chance to look at this?
wam
2018-07-18T22:50:04Z
This is something we're looking for as well.
Thanks.

I tried to set it up hoping it would just work and got exit code 1326 Bad login name or password.
wam
2018-09-06T22:50:02Z
Hi Support,

Any update on this?

This plus the ability to use AD Groups instead of AD Logins would be a HUGE security improvement for us.

VisualCron is literally the last application we use that is considered insecure by our external auditors.
wam
2018-10-17T19:23:09Z
Hi Support,

This is still our top feature request...
michael.miller.weiss
2018-12-07T15:32:33Z
Any update from the VC team on if this is being evaluated?
wam
2019-03-18T17:51:42Z
Hi Henrik,

Any update on when you can get to this?
odendoak
2019-04-26T08:34:33Z
We could really use this as well!

Still no update on this!? 😕
The alternative solution is really a drawback on security.
wam
2019-05-06T14:04:26Z
Henrik,

We're still looking for this feature. This is an important "check the box" feature we need to keep using your product. We have 7 pro licenses, and may add more if you can deliver.
Support
2019-05-09T10:01:52Z
Just so we understand what you want to do:

1. you want to create a Credential with no password
2. you want VC to fetch the temporary password from AD
3. the username with the temporary password is then used in the Task

Is this correct?
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
Support
2019-05-16T14:12:07Z
Just pinging this again to confirm what you want.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
wam
2019-06-05T19:09:52Z
Hi Henrik,

Apologies for the delay - I was out on vacation.

We want "Group Managed Service Account". It's a bit different than what you describe. Here is a link to Microsoft documentation: https://docs.microsoft.c...ervice-accounts-overview 

Here is a potentially helpful API Call: https://docs.microsoft.c...etserviceaccountpassword 

Background Noise
Here is the steps I envision becoming part of your Documentation in VisualCron in order for this to be a complete, functioning feature WITH documentation.

Step 1: Create a new gMSA principal group. We name it <gMsaName>_Principals where <gMsaName> is the name of the group managed service account. (e.g., msaVisualCron_Principals)
Step 2: Add a new Group Managed Service Account in Active Directory (this requires Active Directory schema 2012 or later) - you can do so using the following PowerShell script


Import-module ActiveDirectory
Add-KdsRootKey –EffectiveTime ((get-date).addhours(-10));
New-ADServiceAccount -Name msaVisualCron -DNSHostName visualcronsrv.example.com -PrincipalsAllowedToRetrieveManagedPassword "msaVisualCron_Principals"


Step 3: Install GMSA account on servers which will use it.
Enable-WindowsOptionalFeature -FeatureName ActiveDirectory-Powershell -online -all
Get-ADServiceAccount -Identity msaVisualCron
Install-ADServiceAccount -Identity msaVisualCron
Test-AdServiceAccount -Identity msaVisualCron

Step 4: Test the gMSA works

Simplest way to end-to-end test this in VisualCron on your local development machine is to set-up a SQL Server Developer Edition to run as a group MSA account, and execute a VisualCron SQL Task running as that gMSA. If you use an existing SQL Server instance, make sure you go through SQL Server Configuration Manager to change the Log On As account, and don't do it directly through Local Services. When you do it through Configuration Manager, it will add a dependency to the w32time service to the SQL Server service (the windows time service is required for Kerberos to come up and authenticate, otherwise SQL Server won't start.)

However, perhaps even simpler is creating a simple .NET console app that prints $"Hello World, {Identity}" to standard out, and run that as the gMSA account.
ROBV8R
2019-06-06T03:25:30Z
I'm confused how this solves the original feature request from 2 years ago.

To make sure the requirement is clear:

We need to store Group Managed Service Accounts as a credential type in VisualCron. We want to select that credential from the Credential drop down when executing a task.

Please help me understand how your response addresses the requirement.
wam
2019-06-06T18:01:19Z
Rob, are you replying to me or Support (Henrik)?

Thanks,
John
Support
2019-06-07T08:07:17Z
Originally Posted by: ROBV8R 

I'm confused how this solves the original feature request from 2 years ago.

To make sure the requirement is clear:

We need to store Group Managed Service Accounts as a credential type in VisualCron. We want to select that credential from the Credential drop down when executing a task.

Please help me understand how your response addresses the requirement.



Yes, what you describe is the way it will look for the customer. But behind the scenes, as we understand how GMSA works is that one-time passwords are used. This means that we need to request that from somewhere, either from AD or maybe through Windows API.

The difference, as we see it, is that the password saved in the Credential is not the password used finally. And that before running any Task we need to fetch the actual, temporary, password from AD server.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
wam
2019-06-13T22:49:21Z
Originally Posted by: Support 

Originally Posted by: ROBV8R 

I'm confused how this solves the original feature request from 2 years ago.

To make sure the requirement is clear:

We need to store Group Managed Service Accounts as a credential type in VisualCron. We want to select that credential from the Credential drop down when executing a task.

Please help me understand how your response addresses the requirement.



Yes, what you describe is the way it will look for the customer. But behind the scenes, as we understand how GMSA works is that one-time passwords are used. This means that we need to request that from somewhere, either from AD or maybe through Windows API.

The difference, as we see it, is that the password saved in the Credential is not the password used finally. And that before running any Task we need to fetch the actual, temporary, password from AD server.



Hi Henrik,

Yes, that sounds about right. Please see this API call and let me know how you make out: https://docs.microsoft.c...etserviceaccountpassword 

Also potentially helpful is the DSInternals powershell module: https://github.com/MichaelGrafnetter/DSInternals  and his blog post: https://www.dsinternals....s-from-active-directory/ 
wam
2019-07-22T21:47:40Z
Hi Henrik,

Any update here?
Support
2019-07-23T07:19:48Z
Originally Posted by: wam 

Hi Henrik,

Any update here?



We are looking at this right now but there is a risk that this is not possible to use gMSA accounts that way. We have done some initial tests in 2012 version of Active Directory and there are auth problems in that version. It might work with 2016 - we are installing that now and will test.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
wam
2019-07-25T15:37:38Z
Group managed service accounts are supported in AD 2012 and work with both services and windows task scheduler as well well as offer support for custom applications thru the win32 APIs. Would you mind sharing what scenario is not supported and why?
Support
2019-07-25T16:58:13Z
Originally Posted by: wam 

Group managed service accounts are supported in AD 2012 and work with both services and windows task scheduler as well well as offer support for custom applications thru the win32 APIs. Would you mind sharing what scenario is not supported and why?



It is currently not working outside of IIS and Task scheduler. We are not sure how much more resources we can put on this right now as we spent about a week of development time on this alone.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
wam
2019-07-26T19:54:23Z
Hi Henrik,
I managed to work thru the C# needed to use Group Managed Service Accounts for impersonation. The instructions for creating the group managed service account and principals is included below. Additionally there are few other steps for testing to emulate the environment the VC service runs under. Please review and let me know if this isn't feasible to integrate:


using System;
using System.Data.SqlClient;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;

namespace GroupManagedServiceAccounts
{
    class Program
    {
        /*
         1. Create an AD Group msaTest_Principals
         2. Add the computer you wish to run this code on to the AD Group msaTest_Principals
         3. Create an MSA account using PowerShell: New-ADServiceAccount -name msaTest -DNSHostName msaTest.YOURDOMAIN.com -PrincipalsAllowedToRetrieveManagedPassword msaTest_Principals
         4. Reboot the computer from step #2 to install the GMSA
         5. Download PSExec from SysInternals so we can run this application as SYSTEM (the same account that we run VisualCron under)
         6. Compile this application a C# console application (replace YOURDOMAIN with your domain)
         7. Run psexec.exe -s -i cmd.exe to start a new command window running as system
         8. In the new command window run the executable generated from this code
         9. Troubleshoot any error codes using the Windows Security Event Log
         */

        public const int LOGON32_LOGON_SERVICE = 5;
        public const int LOGON32_PROVIDER_DEFAULT = 0;
        public const string NETWORK_LOGIN_PASSWORD = "_SA_{262E99C9-6160-4871-ACEC-4E61736B6F21}"; 

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public static void Main(string[] args)
        {
            SafeTokenHandle safeTokenHandle;
            try
            {
                var username = "msaTest$";
                var domain = "YOURDOMAIN";

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(username, domain, NETWORK_LOGIN_PASSWORD, LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);

                Console.WriteLine("LogonUser called.");

                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();
                    Console.WriteLine("LogonUser failed with error code : {0}", ret);
                    throw new System.ComponentModel.Win32Exception(ret);
                }

                using (safeTokenHandle)
                {
                    Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                    Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);

                    // Check the identity.
                    Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name);
                    // Use the token handle returned by LogonUser.
                    using (var impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
                    {

                        // Check the identity.
                        Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);

                        //Validate the security credential is used for accessing the network/SQL
                        //using (var connection = new SqlConnection("server=(local);integrated security=true;"))
                        //{
                        //    connection.Open();
                        //    using (var cmd = connection.CreateCommand())
                        //    {
                        //        cmd.CommandText = "SELECT 'Hello'";
                        //        using (var reader = cmd.ExecuteReader())
                        //        {
                        //            reader.Read();
                        //            Console.WriteLine(reader.GetString(0));
                        //        }
                        //    }
                        //}
                    }

                    // Releasing the context object stops the impersonation
                    // Check the identity.
                    Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occurred. " + ex.Message);
            }
            finally
            {
                Console.Read();
            }

        }

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);
    }

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}

Support
2019-07-29T07:41:58Z
Originally Posted by: wam 

Hi Henrik,
I managed to work thru the C# needed to use Group Managed Service Accounts for impersonation.
[/code]



Thanks, I will forward this and I will get back to you with feedback. Will probably be in 1-2 weeks as we are currently preparing for next release and also have some other development we need to do before.
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
Support
2019-08-13T13:28:01Z
We have now implemented partial support for this that means that you should be able to access network files with MSA accounts (all Tasks working with files). Please test build: https://www.visualcron.c....aspx?g=posts&t=9617 

You need to check "MSA" checkbox in the Credential.

I am not sure which Tasks you were interested in?
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
ROBV8R
2019-08-13T13:45:51Z
@Support - Are you referring to "MSA"s (Introduced in Windows Server 2008 R2) or "Group Managed Service Accounts" (created for Windows Server 2012)?
Support
2019-08-14T08:42:00Z
Originally Posted by: ROBV8R 

@Support - Are you referring to "MSA"s (Introduced in Windows Server 2008 R2) or "Group Managed Service Accounts" (created for Windows Server 2012)?



yes
Henrik
Support
http://www.visualcron.com 
Please like  VisualCron on facebook!
Scroll to Top