WPNinjas HeaderWPNinjas Header

Deploy Code Signing Certificate with Intune

5.1.2021 – Updated post to include OMA-URI/Custom configuration option 

In the last years the recommendation to “Code Sign” scripts should have arrived to everybody. Especially when deploying scripts with Intune or ConfigMgr at scale it’s good to sign them.  It sounds simple but regardless most don’t use it. I would like to change that and show you how to start?  

    Table of contents

    In the next sections I will explain these steps in detail.

    Request code sign certificate

    There are multiple options how you can get a certificate. The most common one is buying one from the well known public certificate authorities like DigiCert, Thawte or Comodo.

    If you don’t want to spend money, then you can create a self-signed certificate or if you have a internal certificate authority you can request it from there.

    Internal Certificate Authority

    If you have an internal certificate authority then it’s recommended to use it because then you can also profit from certificate revocation. I will not explain this process in detail because there are many blogs which will show you the correct steps:

    Self Signed Certificate

    Creating your own self signed certificate is simple and can be done with a single PowerShell command. But in this example we will also export the certificate as cer file for deployment. You have to adjust the Subject and FriendlyName properties before executing the code snippet.

    $workingDir = "$env:USERPROFILE\Desktop"
    
    $SSCArguments = @{ 
        Type = "CodeSigningCert" 
        Subject = "CN=YourCompany" 
        KeyUsage = "DigitalSignature" 
        FriendlyName = "Your Company Name" 
        CertStoreLocation = "cert:\CurrentUser\my" 
        } 
    $mycert = New-SelfSignedCertificate @SSCArguments
    
    Export-Certificate -Cert $mycert.PSPath -FilePath "$workingDir\CodeSignCert.cer"

    The certificate is created in your personal store and exported to the $workingDir path:

    Add Code Sign Certificate as Trusted Publisher

    As soon we have our certificate we have to define this certificate as trusted on our endpoints. There are two main issues I saw during my engagements. Because of lack of knowledge the certificate is added to many stores which are not required. For example to “Trusted Root Certification Authorities”, but the following rules should be followed:

    • Public/Private Certificate Authority based
      • Code Sign Certificate –> “Trusted Publisher”
      • Root Certificate Authority of your Certificate –> “Trusted Root Certification Authorities”
      • If there are Intermediate Root Certificate Authorities –> “Intermediate Certification Authorities”
    • Self Signed
      • Code Sign Cert –> “Trusted Publisher” and “Trusted Root Certification Authorities”

    Additionally, the certificates should be added to the machine and not to the user store to be valid for all users and system processes like Intune and MEMCM is using.

    In a AD/GPO based environment it’s simple to deploy the certificates but with Intune we need some help of a PowerShell script or a custom configuration profile.

    AD and GPO based deployment

    1. Start the Group Policy Management snap-in.

    2. Find an existing Group Policy Object (GPO) or create a new GPO to contain the certificate settings. Ensure that the GPO is associated with the domain, site, or organizational unit (OU) where the appropriate user and computer accounts reside.

    3. Right-click the GPO, and then click Edit.

    4. In the console tree, open Computer Configuration\Policies\Windows Settings\Security Settings\Public Key Policies, right-click Trusted Publishers, and then click Import.

    5. On the Welcome to the Certificate Import Wizard page, click Next.

    6. On the File to Import page, type the path to the appropriate certificate files (for example, CodeSignCert.cer), and then click Next.

    7. On the Certificate Store page, click Place all certificates in the following store, and then click Next.

    8. On the Completing the Certificate Import Wizard page, verify that the information you provided is accurate, and then click Finish.

    9. Repeat steps 4 through 8 if you have a self signed certificate or the root ca is not already in the Trusted Root Certificate Authorities. Just instead of Trusted Publishers choose Trusted Root Certification Authorities in step 4. 

    Intune based deployment - Self Signed

    With Intune we have a simple configuration profile to deploy certificates to the trusted Root or Intermediate Certification Authorities stores, but Trusted Publishers are not possible. Therefore, we have to leverage a PowerShell Script or a custom configuration profile for that. The custom configuration profile option is perfectly described in the Tech Community. This section contains the information the PowerShell way. 

    To simplify the deployment we add the cer file encoded to the script.

    First we need to encode the created cer file as base64 with the following snippet. If you have used my first snipped to create the certificate the cer file should be on your desktop and the snippet will just work and create a ps1 script ready to deploy. Otherwise you have to adjust the path ($workingDir and $certFileName variable):

    $workingDir = "$env:USERPROFILE\Desktop"
    $certFileName = "CodeSignCert.cer"
    
    $b = Get-Content "$workingDir/$certFileName" -Encoding Byte
    $b64 = [Convert]::ToBase64String($b) 
    $b64 | Out-File "$workingDir/CodeSignCert.b64"
    
    #Insert content of the created b64 file int to the following string of the variable $b
    
    @"
    `$b64 = "$b64"
    `$dec = [Convert]::FromBase64String(`$b64)
    [IO.File]::WriteAllBytes("`$(`$env:TEMP)\bcodesign.cer", `$dec)
    Import-Certificate -FilePath "`$(`$env:TEMP)\bcodesign.cer" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher
    
    Import-Certificate -FilePath "`$(`$env:TEMP)\bcodesign.cer" -CertStoreLocation Cert:\LocalMachine\Root
    "@ | Out-File -FilePath "$workingDir/DeployCodeSignCert.ps1"

    The following files should be created after the execution:

    The content of the .ps1 file will look similar to the following screenshot and is doing everything when using a self signed certificate including adding the certificate to the Trusted Root Certification Authority store.

    To start the deploymen, open the Microsoft Endpoint Manager admin center and select Devices.

    Then select Scripts in the navigation:

    Now you can click on Add and select Windows 10.

    Provide a meaningful Name for the script, then click on next.

    In this step browse for the generated ps1 file. Important is, that you don’t select Enforce script signature check. Then click on next.

    Assign the script to the devices you wish to use code signed scripts in the future. I select All devices and click on next.

    Now all is ready and you can click on Add to start the deployment.

    After a short while all devices should have the certificate installed.

    Create script and Sign it

    The environment is now prepared and we can start creating a first script and code sign it. The creation is up to you, but then you can use the following code snippet to sign the script. After each change to the ps1 file you have to repeat the signing process.

    When executing the snippet, then you will get a grid view window to select your code sign certificate and get the possibility to specify the path to your PowerShell script.

    $signingcert = (Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert) | Out-GridView -OutputMode Single
    
    Set-AuthenticodeSignature -Certificate $signingcert

    Now all is prepared for the deployment in the next section.

    Deploy signed script with MEM Intune

    You can now create and the script in Intune like before, but with one difference: You can now select Enforce script signature check!

    With these few extra steps you can make your deployments much more secure by adding these two capabilities:

    • Content source – code signing identifies that the software or application is coming from a specific source (a developer or signer).
    • Content integrity code signing also ensures that a piece of code has not been altered and determines whether code is trustworthy for a specific purpose.

    Follow me

    2 Comments

    Andre · January 28, 2021 at 20:34

    Instead of using script feature in Intune, I could create an app and deploy the PS1 script to all devices, right? In that way, I would ensure that Intune will keep trying to install the certificate instead of running the script once.

    Leave a Reply

    Avatar placeholder

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.