0

I have a 2 powershell files. One invokes createInstallSSLCertificates.ps1 which will create SSL keys, certificates, etc. At the end, after installing the private CA and public pfx certificate, it returns the thumbprint of the public certificate.

$rootobj = Import-Certificate -FilePath $rootcert -CertStoreLocation "cert:\$certuser\Root"
$personalobj = Import-PfxCertificate -FilePath $serverpfx -CertStoreLocation "cert:\$certuser\My" -Password $pfxexportpassword
if ($personalobj -and $rootobj) {
    Write-Host "Root Thumbprint: $($rootobj.Thumbprint)`n Personal Thumbprint: $($personalobj.Thumbprint)"
    return $personalobj.Thumbprint.ToString()
        } else {
    ...
}

The issue comes when looking at the return type on the calling script:

 $personalCertThumbprint = &$install_certs_path -InstallCerts $true -user "LocalMachine"

The value returned from the $install_certs_path is: > $personalCertThumbprint = C:\Users\Administrator\Documents\installer-and-scripts\CAcerts_certs_0496 C:\Users\Administrator\Documents\installer-and-scripts\CAcerts_certs_0496\CAcerts_server_ext.ext EC0D88A1C9D558B6E5DF5165B43938F7BC84E6B7

and not what i expect: > $personalCertThumbprint = EC0D88A1C9D558B6E5DF5165B43938F7BC84E6B7

I can't figure out why folder and .ext file paths are returned from the file. I've made sure that $personalobj.Thumbprint is just the thumbprint and not a strange string with paths. Is there some implicit value returning happening with powershell?

EDIT: showing the show code for the certificate creating script:

param (
    [Parameter(Mandatory=$false, HelpMessage="After creation of the certificates, should they be installed.")]
    [bool]
    $InstallCerts=$false,

    [Parameter(Mandatory=$false, HelpMessage="If the program should pause after creating the EXT file. This allows for more DNS names to be specified in the certificate")]
    [bool]
    $PauseOnExtFile=$false,

    [Parameter(Mandatory=$false, HelpMessage="The SAN, DNS, or Hostname of the server that the personal certificate will be installed on")]
    [string]
    $SAN=$(hostname),

    [Parameter(Mandatory=$false, HelpMessage="The common / friendly name of the personal signed certificate")]
    [string]
    $PersonalCommonName=$(hostname),

    [Parameter(Mandatory=$false, HelpMessage="The common/ friendly name of the CA root certificate")]
    [string]
    $RootCommonName="COMPANY123",

    [Parameter(Mandatory=$false, HelpMessage="(LocalMachine | CurrentUser)")]
    [string]
    $user="LocalMachine"
)

if (!($user.Contains("LocalMachine")) -and !($user.Contains("CurrentUser"))) {
    Write-Host "`$user must be either LocalMachine or CurrentUser, not '$user'"
    Exit
}

################## Variables #######################
# change these as you necessary
$base = "CAcerts"
$certuser = $user
$rootpassword = "password"
$pfxexportpassword = "password"
$country = "CH"
$state = "BIOBIO"
$city = "Concepcion"
$org = "mycompany"
$unit = "UNIT"

################ Making filepaths into variables and directory ##################3

# adding random number onto the directory name 
$epochseconds = Get-Date (Get-Date).ToUniversalTime() -UFormat %s
$epochseconds = $epochseconds.Replace(".", "")
$ran = $epochseconds.Substring($epochseconds.Length-4, 4)

$cwd = Get-Location
$dirname = join-path -Path $cwd -ChildPath "$($base)_certs_$($ran)"
$rootkey= $base + "_root_key.key"
$rootpem= $base + "_root_pem.pem"
$rootcert= $base + "_root_ca.crt"
$serverkey= $base + "_server_key.key"
$servercsr= $base + "_server_csr.csr"
$servercert= $base + "_server_cert.crt"
$serverpfx= $base + "_server_pfx.pfx"
$ext_file= $base + "_server_ext.ext"

$rootkey= join-path $dirname $rootkey
$rootpem= join-path $dirname $rootpem
$rootcert= join-path $dirname $rootcert
$serverkey= join-path $dirname $serverkey
$servercsr= join-path $dirname $servercsr
$servercert= join-path $dirname $servercert
$serverpfx= join-path $dirname $serverpfx
$ext_file= join-path $dirname $ext_file

New-item -ItemType Directory $dirname
New-Item -Path $ext_file -ItemType File

################## Install OPENSSL #######################
if (!(Get-Command openssl -ErrorAction SilentlyContinue)) {
    Write-Host "openssl is not a recognized powershell command. Looking to install openssl from chocolatey." -ForegroundColor Yellow
    # install choco
    if (!(Get-Command choco -ErrorAction SilentlyContinue)) {
        Set-ExecutionPolicy Bypass -Scope Process -Force; 
        [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; 
        Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

        # reset env variables to prevent having to reopen shell
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
    }

    # install openssl
    if (!(Get-Command openssl -ErrorAction SilentlyContinue)) {
        choco install openssl.light -y
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
    }
}
################## CREATE CERTS #######################

# Make private root key
Write-Host "Creating root key"
openssl genrsa -des3 -passout pass:$rootpassword -out $rootkey 2048 
if ( !(Test-Path -Path $rootkey -PathType Leaf)) {
    Write-Host("$rootkey was not created")
}

# make root certificate CA
Write-Host "Creating root cert CA"
openssl req -x509 -new -nodes -key $rootkey -sha256 -days 3650 -out $rootcert -passin pass:$rootpassword -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$RootCommonName"
if ( !(Test-Path -Path $rootcert -PathType Leaf)) {
    Write-Host("$rootcert was not created")
}

# make a PEM privacy enhanced mail key
Write-Host "Creating root PEM"
openssl req -x509 -new -nodes -key $rootkey -sha512 -days 3650 -out $rootpem -passin pass:$rootpassword -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$RootCommonName"
if ( !(Test-Path -Path $rootpem -PathType Leaf)) {
    Write-Host("$rootpem was not created")
}

# make server private key
Write-Host "Creating server private key"
openssl genrsa -out $serverkey 2048
if ( !(Test-Path -Path $serverkey -PathType Leaf)) {
    Write-Host("$serverkey was not created")
}

# create ext file
Write-Host "Creating Ext file"
$content = 
"authorityKeyIdentifier=keyid,issuer 
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = @alt_names

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1 = $SAN"

$content | Out-File -FilePath $ext_file -Encoding utf8
if ($pauseOnExtFile) {
    write-Host "Pausing execution so you can manually change the EXT file: '$ext_file'
    Add additional DNS names if desired.
    $_pause = Read-Host "Hit enter when ready to continue."
}


# create server .csr file
Write-Host "Creating Server CSR"
openssl req -new -key $serverkey -out $servercsr -subj "/C=$country/ST=$state/L=$city/O=$org/OU=$unit/CN=$PersonalCommonName"
if ( !(Test-Path -Path $servercsr -PathType Leaf)) {
    Write-Host("$servercsr was not created")
}

# server cert
Write-Host "Creating Server CERT"
openssl x509 -req -in $servercsr -CA $rootpem -CAkey $rootkey -CAcreateserial -out $servercert -days 3650 -sha512 -extfile $ext_file -extensions 'req_ext' -passin pass:$rootpassword
if ( !(Test-Path -Path $servercert -PathType Leaf)) {
    Write-Host("$servercert was not created")
}

# convert crt to pfx formatting
Write-Host "Converting CERT to PFX"
openssl pkcs12 -export -inkey $serverkey -in $servercert -passout pass:$pfxexportpassword -name $base -out $serverpfx
if ( !(Test-Path -Path $serverpfx -PathType Leaf)) {
    Write-Host("$serverpfx was not created")
}

################## INSTALL CERTS #######################
if ($InstallCerts) {
$pfxexportpassword = ConvertTo-SecureString -String $pfxexportpassword -Force -AsPlainText
    try {
        $rootobj = Import-Certificate -FilePath $rootcert -CertStoreLocation "cert:\$certuser\Root"
        $personalobj = Import-PfxCertificate -FilePath $serverpfx -CertStoreLocation "cert:\$certuser\My" -Password $pfxexportpassword
        Write-Host "Root Certificate installed in $certuser\Trust Root CA as $RootCommonName"
        Write-Host "Server Certificate installed in $certuser\Personal as $PersonalCommonName. Thumbprint: ${personalobj.Thumbprint}"
        Write-Host "Program was successful creating certs $base."
        Write-Host "Exiting ...."

        if ($personalobj -and $rootobj) {
            Write-Host "Root Thumbprint: $($rootobj.Thumbprint)`n Personal Thumbprint: $($personalobj.Thumbprint)"
            return $personalobj.Thumbprint
        } else {
            return "Error installing the certificates"
        }
    } catch {
        Write-Host "Installation failed. of certificates. Check permissions and try again."
        Exit
    }
}


mklement0
  • 382,024
  • 64
  • 607
  • 775
Lacrosse343
  • 491
  • 1
  • 3
  • 18
  • nothing wrong with ```$personalobj.Thumbprint```, btw. you do not need to call the method ```ToString()```, it is already a string. Guess we need to see the whole scriptcode, most probably you output those paths earlier.... – Toni Nov 02 '22 at 18:54
  • I added the whole file for better context – Lacrosse343 Nov 02 '22 at 19:06
  • In short: any output - be it from a PowerShell command, an operator-based expression, or a .NET method call - that is neither captured in a variable nor redirected (sent through the pipeline or to a file) is _implicitly output_ from a script or function. To simply _discard_ such output, use `$null = ...`. If you don't discard such output, it becomes part of a script or function's "return value" (stream of output objects). See the linked duplicate for more information. – mklement0 Nov 02 '22 at 21:50

1 Answers1

2

As you invoke a script you must take care what it outputs on which streams, e.g.:

New-item -ItemType Directory $dirname
New-Item -Path $ext_file -ItemType File

The output of those two commands will also be part of the information stored in the variable $personalCertThumbprint.

To avoid that do:

$null = New-item -ItemType Directory $dirname
$null = New-Item -Path $ext_file -ItemType File

Btw. in case of your parameter specification take a look at SWITCH:

[bool]$InstallCerts -> [switch]$InstallCerts

[switch] is by default FALSE and once specified it becomes TRUE or you can specify it explicitly -InstallCerts:$true.

Toni
  • 1,738
  • 1
  • 3
  • 11