Creating an artifact configuration

Abstract

The artifact configuration describes the structure of the artifacts you want to sign. For simple artifacts, you can use predefined configurations to get started quickly. For signing several artifacts together, and for more complex artifacts, specify the structure of your artifact and provide signing directives using XML.

Tips:

  • Download the schema file and use a schema-aware XML editor, such as Microsoft Visual Studio, to create your artifact configuration.
  • If you don’t know the internal structure of your artifact, extract container files to your disk first.

Deep signing

In case you have more complex, nested artifacts, you might want to not only sign the container itself (for instance, an MSI installer package), but also all files that are shipped within the container (e.g. .exe and .dll files within the MSI installer). Therefore, every container format can contain multiple other file or directory elements to be signed. Each of those will be extracted, signed, and then put back into the container file during the signing process. In order for SignPath to find the right file, all inner elements need a path attribute.

File elements

Every XML description is wrapped in an root element, containing exactly one file element, which specifies the type of artifact. Within container files and directories, file elements can be specified for deep signing.

Element Container format Signing directive Extensions Description
<pe-file>
No
<authenticode-sign>
.acm, .ax, .cpl, .dll, .drv, .efi, .exe, .fon, .mui, .ocx, .scr, .sys, .tsp Microsoft Portable Executable files: EXE, DLL, and some other executable file formats
<powershell-file>
No
<authenticode-sign>
.ps1, .psm1, psd1, .psdc1, .ps1xml PowerShell scripts or modules
<zip-file>
Yes (none) .zip ZIP archives (can’t be signed)
<msi-file>
Yes
<authenticode-sign>
.msi, .msm, .msp Microsoft installer files
<cab-file>
Yes
<authenticode-sign>
.cab Windows cabinet files
<appx-file>
Yes
<authenticode-sign>
.appx, .appxbundle App packages for Microsoft Store/Universal Windows Platform (Deep signing is not yet supported)
<opc-file>
Yes
<opc-sign>
.vsix, .xps, … Open Packaging Conventions (OPC) files. Supported formats include:

  • Visual Studio Extensions (VSIX)
  • Open XML Paper Specification (OpenXPS)
  • Office Open XML files (documents, presentations and workbooks)
  • Note that while OPC siging can be applied to all OPC formats, many specific formats do not use signing or require a different signing format
<nupkg-file>
Yes
<nuget-sign>
.nupkg NuGet packages
<directory>
Yes
<clickonce-sign>
See next section
  • The simplest artifact configuration only contains a single file element and a signing directive. Consider using a predefined artifact configuration.
  • If you want to sign multiple artifacts in one step, you need to package them into a ZIP archive before processing.
  • If you want to deep-sign container files, you need to specify their internal structure.
  • You can combine signing multiple artifacts with deep signing.

Examples

Predefined configuration for single EXE file

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration
    xmlns="http://signpath.io/artifact-configuration/v1">
  <pe-file>
    <authenticode-sign />
  </pe-file>
</artifact-configuration>

Multiple artifacts can be signed in a single step by packing them into a ZIP container

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration
    xmlns="http://signpath.io/artifact-configuration/v1">
  <zip-file>
    <pe-file path="app.exe">
      <authenticode-sign />
    </pe-file>
    <powershell-file path="setup.ps1">
      <authenticode-sign />
    </powershell-file>
  </zip-file>
</artifact-configuration>

Deep signing of an MSI installer

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration
    xmlns="http://signpath.io/artifact-configuration/v1">
  <msi-file>
    <directory path="libs">
      <pe-file path="common.dll">
        <authenticode-sign />
      </pe-file>
    </directory>
    <pe-file path="main.exe">
      <authenticode-sign />
    </pe-file>
    <authenticode-sign />
  </msi-file>
</artifact-configuration>

<directory> element

All supported container formats have an internal directory structure. You can see this structure if you extract a container to a local disk.

Directory elements specify a directory in a container file, or a subdirectory within a directory. You can use directory elements for ClickOnce signing and structuring your configuration.

Example

Structuring with a directory element

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1">
  <zip-file>
    <directory path="environments/*" max-occurs="3">
      <pe-file path="*.dll" min-occurs="5" max-occurs="5">
        <authenticode-sign />
      </pe-file>
    </directory>
  </zip-file>
</artifact-configuration>

ClickOnce signing

Since ClickOnce signing is a signing method for directories, not for files, you need to specify a directory element for this method.

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1">
  <zip-file>
    <directory path=".">
      <clickonce-sign />
    </directory>
  </zip-file>
</artifact-configuration>

File and directory sets

Complex structures can be expressed by enumerating multiple files or directories using one of the following file or directory set elements:

  • <directory-set>
  • <pe-file-set>
  • <zip-file-set>
  • <msi-file-set>
  • <cab-file-set>
  • <opc-file-set>
  • <nupkg-file-set>

Each set element contains

  • a list of
    <include>

    elements specifying which items will be processed

  • a
    <for-each>

    element that will be applied to all

    <include>

    elements of the set

For example, the following XML describes an MSI installer package containing several nested EXE and DLL files to be signed:

MSI file with complex structure

<?xml version="1.0" encoding="utf-8" ?>
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1">
  <msi-file>
    <directory-set>
      <include path="Component_1" />
      <include path="Component_2" />
      <include path="Component_3" />
        <for-each>
          <pe-file-set>
            <include path="main.exe" />
            <include path ="resources\*.resource.dll" max-occurs="unbounded" />
            <for-each>
              <authenticode-sign />
            </for-each>
         </pe-file-set>
       </for-each>
    </directory-set>
    <authenticode-sign /> <!-- finally sign the MSI file -->
  </msi-file>
</artifact-configuration>
Example of a directory structure that would match this configuration:

  • MyApp.msi
    • Component_1/
      • main.exe
      • resources/
        • de.resource.dll
        • en.resource.dll
        • fr.resource.dll
    • Component_2/
      • main.exe
      • resources/
        • en.resource.dll
    • Component_3/
      • main.exe
      • resources/
        • de.resource.dll
        • en.resource.dll
        • fr.resource.dll

Like in the example above, every path attribute can contain the following wildcard patterns:

Wildcard Description
*
Matches any number of any character (including none, excluding the directory separator)
?
Matches any single character
[abc]
Matches one character given in the bracket
[a-z]
Matches one character from the range given in the bracket
[!abc]
Matches one character that is not given in the bracket
[!a-z]
Matches one character that is not from the range given in the bracket
**
Matches any number of path / directory segments. When used, they must be the only contents of the dedicated segment.

If wildcards are used, optional

max-occurs

and

min-occurs

parameters can be specified to limit the number of files which are allowed to match the wildcard expression. Both default to

1

. (You can also use

min-occurs="0"

for optional elements even without wildcards.)

Signing methods

File and directory elements can contain signing directives. The signing directives must use signing methods that are available for the parent element. For file and directory sets, specify the signing directive in the element.

Examples:

  • <nupkg-file>

    supports

    <nuget-signing/>
  • <nupkg-file-set>

    supports

    <nupkg-signing/>

    within the

    <for-each>

    element

Extracting artifact packages

You can use the following tools in order to manually extract files from your artifacts. From the extracted file structure, you can then easily create a matching artifact configuration.

We recommend that you apply these tools to all contained files recursively and create a very specific artifact configuration.

File type Recommended tools
ZIP, CAB Extract using tools like WinZip or 7-Zip or Windows Explorer.
VSIX, NUPKG These are just special ZIP archives. Either change the extension to .ZIP or use a tool like 7-Zip to directly extract their contents.
MSI Use the Windows tool msiexec.exe to perform an administrative install. Note that this might execute parts of the MSI file, so only use this for trusted files.

msiexec /a filename.msi TARGETDIR=c:\full-path
LOGIN