DigiCert eToken keeps removing private key on reboot. I have to re-issue certificate regularly - code-signing

I have a DigiCert eToken that I use to sign released artifacts via TeamCity. Signer machine is an agent in TeamCity that is invoked from the build pipeline.
The problem is that on a reboot of the machine, the private key vanishes. DigiCert util shows 'repair the certificate' option, but clicking that says "The private key for this certificate could not be found on this machine or current user key stores".
The DigiCert order page only gives two options: reissue certificate or view receipt.
This happens recurrently. Contacted DigiCert, they said it could be because reboot changes the machine for key to get invalid somehow and they suggest re-issue each time. However, this is toil for something that should be automated.

Related

How can I verify and run a signed PowerShell script only trusting the Issuing Certificate (root) and not the Signing Certificate (leaf) itself?

I have a Windows image that uses the PowerShell execution policy AllSigned
I also have a PowerShell script that is signed by a signing certificate issued by an internal CA
The certificate of the issuing CA is installed/trusted on the target machine
When I sign the PowerShell script, I am including the full certificate chain (IncludeChain = 'All')
The certificate chain looks like this:
|- Issuing CA Certificate
|- Signing Certificate
The PowerShell script is signed by the Signing Certificate, but we are not installing that certificate on our target machine. We are only installing the Issuing CA Certificate into the Trusted Publishers and other certificate stores.
This method works when we sign our custom application binaries using the Signing Certificate (we use Windows Defender Application Control to ensure that any applications running on our target are signed by trusted publishers) but it does not work when running PowerShell scripts.
According to this MSDN community post, PowerShell uses Known Publisher rules, which state that the Signing Certificate itself has to be in the Trusted Publishers certificate store.
This is not ideal, as the signing certificate we use to sign the PowerShell scripts is not something we want to ship out, nor will it be valid anymore by the time our product ships.
I understand that if I use a timestamp server when signing the PowerShell scripts, that the signature will still be considered valid if the signature was generated within the validity window of the signing certificate, but this is not our preferred solution.
Ideally I would like to know if it is possible, and how, to have PowerShell use the Issuing CA Certificate to validate the signed PowerShell scripts. (i.e. Known Issuer rules)
In the case that it's not possible, I would like to know why Microsoft departed from the practice of allowing you to validate signatures without explicitly trusting the signing certificate (i.e. using the issuing certificate to validate it).
Any help would be greatly appreciated.
There is a difference between deployment and the running of PowerShell scripts.
The confusion is that Windows Defender Application Control can use code signing 2 different ways, for 2 different reasons, and PowerShell has only ever supported one. Windows Defender Application Control can use code signing:
With a trusted Issuing CA Certificate to authenticate applications. This is the situation when your company wants to share many internal applications among all employees easily. It is also used for "trusted" Microsoft Store applications.
Because "normal" people don't blindly trust all applications and generic certificate authorities, you can instead deploy based off of trusting just the Signing Certificate for verification. (see Catalog Files). This is so that you could deploy applications with certificates that may not have an accessible CA. e.g. if you singed the application with an internal CA and you sell it to another company, or if you are using a self signed certificate.
Windows Defender Application Control primary purpose is for Application deployment/control, and a byproduct is that it can do PowerShell scripts as well. Most "normal" applications can run with "invalid" or "broken" certificates with incomplete certificate chains. The certificate was only used to control the distribution of the code and validation that the application was not tampered with/changed, and has nothing to do with the active "running" of the code.
PowerShell, on the other hand, when running with AllSigned, always validates the entire chain before running. It doesn't care about the distribution, it cares about what it runs. That means that the entire certificate chain needs to be present and trusted on the running machine. Yes, that means that if you sign with an internal CA, you need the Issuing CA Certificate, and the Signing Certificate distributed and trusted by the running party.
This leads you to 3 options:
Self signed certificate - This is ok for personal/development projects, and marginally better than distributing unsigned code.
Internal CA certificate - This is ok for internal projects. In this case, yes, you would have to share the entire certificate chain if you wanted to distribute.
Global/Public CA Certificate - This is the recommended method if you are distributing publicly/commercially. The Public CA's are trusted, and code signing certificates can be bought from places like DigiCert and can last 3 years. I know, for me, I would feel much more comfortable running code signed by a DigiCert over having to mess with internal or self signed certificates.
That doesn't make sense.
If the internal root CA certificate is in your trusted root CA store and the intermediate in your trusted intermediate store. Then a PS script is signed by a certificate with a trusted chain back to the trusted root, it should trust the signing of the certificate.
There should be no difference between an internal trusted CA and a public trusted CA.
If anything a code signing certificate issued by an internal CA is more trustworthy than a public signed one. Internal processes and controls mean only actual trusted internal publsihers can get one, unlike a public code signing cert bought for a small amount.

Two valid certificates equal one invalid certificate

I'm fairly new to the whole certificate shebang and not a versed Linux admin.
In our company, we run a Windows domain, but we also have some CentOS servers for different services.
On one of said servers we have our ticket system, which is browser based. I want to certify it with a certificate, signed by our Windows root CA, but no matter what I do, the certificate is shown as invalid in the browser.
Funny enough, both certificates in the chain (CA -> server) are shown as valid.
I already did the following:
start certificate process from scratch
tried different certificate formats (.cer, .pem)
verified server cert with root cert
checked validity with openssl (OK)
checked SSL connection with openssl, no issues
added root cert to Linux server trusted CA store
recreated cert chain (of 2)
restarted Apache over and over
reset browser cache
tried different browser
checked DNS entries
checked, if root CA is trusted in Windows (it is)
manually installed server cert in my browser
Both the server cert and the root cert show up as valid in the browser, with the correct relation.
I'm completely lost here. Is there some key step I forgot and not one of the ~30 guides I read forgot to mention?
Any help is greatly appreciated
Your question is missing some information:
Did you check the SSL connection from outside the server?
Did you verify the RootCA cert is inside the cert-store of the server (sometimes it is rejected without error messages)?
I would check the reason for rejecting the certificate in the browser (FireFox is usually more informative than Chrome), and look for the error-code.
Reasons can be (some of which you have already verified):
Wrong certificate properties (missing the required values in the "usage" attribute)
Wrong domain name
Expired certificate
Certificate could not be verified on the client-side
See this image as an example of an error code:
https://user-images.githubusercontent.com/165314/71407838-14f55a00-2634-11ea-8a30-c119d2eb1eb1.png

How to set up a developer security certificate in under 5 minutes

I've just spent 2 days unsuccessfully setting up a security certificate for Apache on Windows. I tried:
Let's Encrypt (doesn't work with local domains)
A self-signed certificate (most instructions are for Apache on Linux, or IIS on Windows)
I finally managed to create a self-signed certificate using the Windows version of OpenSSL:
C:\Server\Apache24\conf>openssl req -x509 -newkey rsa:2048 -keyout projectsplat.dev.key -out projectsplat.dev.crt -days 1000 -nodes
Generating a 2048 bit RSA private key
................................................+++++
...................+++++
writing new private key to 'projectsplat.dev.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
I'm a bit confused because it never asked for the domain name, but it installed successfully in Apache without complaining. However, when I open the URL on my browser, I get a message:
Your connection is not private
Attackers might be trying to steal your information from projectsplat.dev (for example, passwords, messages, or credit cards). Learn more
NET::ERR_CERT_AUTHORITY_INVALID
projectsplat.dev normally uses encryption to protect your information. When Vivaldi tried to connect to projectsplat.dev this time, the website sent back unusual and incorrect credentials. This may happen when an attacker is trying to pretend to be projectsplat.dev, or a Wi-Fi sign-in screen has interrupted the connection. Your information is still secure because Vivaldi stopped the connection before any data was exchanged.
You cannot visit projectsplat.dev right now because the website uses HSTS. Network errors and attacks are usually temporary, so this page will probably work later.
I found instructions for installing the self-signed certificate in Chrome/Opera/Vivaldi and followed them, getting a "Successfully installed" message at the end. Great! So I refreshed the page and got exactly the same message as above.
I looked up HSTS but I didn't see any information about resolving this error.
How can you create an SSL certificate in under 5 minutes that just works?
Open port 80 & 443 to the internet, run LetsEncrypt, then close the ports.
It shouldn't be a big risk letting a new, fully patched version of IIS talk to the internet unless you have private stuff there.
You'll need to do it again in 90 days.

Running CodeSigned powershell scripts on target machines

Goal: I would like to run my custom powershell scripts that are signed with a valid certificate against target machines with their powershell execution policy set to “AllSigned” without having to install another certificate on the target machine.
Problem: The powershell scripts will not run until I install the public key of the certificate I used to sign the scripts as a trusted publisher (lets call it MyCert.cer) on the target machine.
Possible Misunderstanding: I could be misunderstanding the way code siging works with my “problem” above. However I was under the impression that since windows comes with DigiCert certificates installed by default as “Trusted Root Certification Authorities” (See image below) that all I would need for my signed scripts to work is signing them from a digicert authority.
My Certificate details:
I purchased a code signing certificate from DigiCert. The certificate is valid and has an “EKU” of “Code Signing (1.3.6.1.5.5.7.3.3)”.
Certificate chain:
Final Thoughts: I signed the powershell scripts using the cmdlet “Set-AuthenticodeSignature” and my issued code signing certificate. The scripts will run if I install the MyCert.cer public key as a “Trusted Publisher” on the target machine. However, I would like to not have to touch the target machine and be able to run my code signed scripts against said machine. Is this possible? Have I purchased the wrong certificate for my goal? Or is an entry to the Trusted Publishers certificate store required for running code signed scripts?
Thank you for your time.
Update: Here is the command I used to sign the powershell scripts.
Set-AuthenticodeSignature -Certificate $cert -FilePath $FileToSign -IncludeChain all
I wanted to let everyone know that I did include "All" for the includeChain. I have also tried using digiCerts timestamp server for the -TimestampServer parameter. However adding the timestamp does not make a difference for running the script. The -TimestampServer parameter as to my understanding is for when a certificate expires and need to be re-validated. However the certificate I am using is still current and not expired.
You are finding the intended behavior of the AllSigned Execution Policy. From Get-Help about_Execution_Policies you will see:
AllSigned
- Scripts can run.
- Requires that all scripts and configuration files
be signed by a trusted publisher, including scripts
that you write on the local computer.
The short answer is that you'll need to trust your cert on all your computers (the easy way to do this is with Group Policy). The Group Policy Object that you'll write will modify Computer Configuration\Windows Settings\Security Settings\Public Key Policies\Trusted Publishers and then you'll need to follow the instructions in the Certificate Import Wizard. The key thing here is that the certificate can be traced back to the Trusted Root Certification Authorities in your organization, so it's a very good thing that you bought a Digicert certificate and that your organization trusts Digicert certs.
So why does Digicert show up under Trusted Root Certification Authorities? The answer here is pretty simple. It means that your organization recognizes Digicert certificates and allows them to be trusted. This doesn't mean that every single Digicert certificate automatically gets a pass, it just means that they are allowed to be installed to your domain. I am gonna pick on Comodo, since they're close alphabetically and they don't show up in your screenshot. Because Comodo also gives out digital certificates, if I were to sign my scripts with my Comodo cert and try and install that certificate across your domain, it wouldn't stick since Comodo is not a Trusted Root Certification Authority in your domain.
I hope that helps explain what's going on!

Renewing the queue manager's certificate

One of our queue managers certificate is about to expire, it is been advised that renewing it is much cheaper than replacing the old one. These are the below steps which we are following(Through IBM Key Management):
Choose the personal certificate and select re-create - Renewal.csr
Send the Renewal.csr to CA for COMODO certificate - RenewedComodo
Choose the personal certificate and select Receive to import RenewedComodo. ( Refresh Security )
When creating a new certificate we opt for Personal Certificate Request and select new.This is the first step. and we follow the 2 and 3 steps.
Here is my query, other than selecting the re-create, there is no difference I had set up.
When I have two certificates as RenewalCOMODO and oldCOMODO, how do queue manager knows which is righteous.?
If it selects which is not expired, won't it be having the expired one in the database?
If we need to delete the old one, after adding the renewed one, How will it be different from replacing the certificates?
This will require a little background before getting to the answers.
When you initially created the CSR what you actually got was a public/private key pair and a Certificate Signing Request or "CSR". The CSR contains the public key and the requested attributes such as Distinguished Name. The CSR is signed with your private key so that any recipient can use the embedded public key to validate that the CSR and the requested attributes have not been tampered with.
What is less well known is that the CA is not bound to apply all the attributes that were provided in the CSR. For example, if the certificate purchased is a Domain Validated certificate and the CSR contains values for the OU field, the CA will simply delete them leaving only the DN and SAN fields plus their own information. Thus the certificate you get back may have different fields than the original CSR.
When you recreate the CSR from an in-use certificate the same process occurs again except that new CSR reflects any changes that the CA made originally. Close inspection of the original CSR and the newly generated one commonly show differences in the SAN or that an email contact has been added to the DN. However, from the CA's point of view these differences are cosmetic.
With that in mind, let's look at the questions again.
When I have two certificates as RenewalCOMODO and oldCOMODO, how do queue manager know which is right?
Assuming that you are talking about the artifacts the CA has provided after responding to the original and renewal CSR, the QMgr does not know which is which. You can run the receive command on either and, assuming both of them were signed by the same CA and use the same signer chain, either will work.
It is the administrator's responsibility to verify that the correct certificate is installed.
If it selects which is not expired, won't it be having the expired one in the database?
No. Each successful receive command keeps the private portions of the personal certificate and replaces the public portions. The label is associated with the private portion and this is checked for uniqueness so you cannot (or at least should not if there are no bugs) be able to have two copies in the same KDB.
If we need to delete the old one, after adding the renewed one, How will it be different from replacing the certificates?
Just make sure you receive the correct certificate. Always do a runmqakm -cert -details command or inspect the cert using the GUI.
Additional recommendations:
Always make a copy of the KDB before working on it.
Keep copies of your CSRs and certs in the KDB directory.
I like to use timestamps in the file names so it is obvious what the history was. My file names all start with YYYYMMDD like 20150908_QMName_CSR.arm and 20150908_QMName_CSR_signed.arm.
Make sure that the file permissions of the certificate files, KDB, and directory holding them are set to deny any access by anyone other than the MQM service account. If that's not possible, allow group access but make sure the members of the mqm group are as few as possible. Anyone who can read the certificates can use them. It is not necessary to know the password to the KDB to use the certs it contains.
When performing maintenance, I like to make a new copy of the KDB (with timestamped file name as described earlier) and when I'm sure it is ready I change the QMgr's SSLKEYR attribute to point to it. I then change the old file to be read-only and issue RESET SECURITY TYPE(SSL) on the QMgr.
Always remember to issue RESET SECURITY TYPE(SSL) on the QMgr. It is a rather disruptive command so try to not issue it when the QMgr is busy. It will require all channels to shut down and lots of reconnect attempts will prevent it from completing quickly.

Resources