First of all I will try to answer your questions separately:
- Protects the private key from being copied:
Only the cryptographic hardware (smartcard or hsm) can really protect the key from being copied. Windows certificate store (even with non-exportable option as you correctly noted) or PKCS#12 (PFX) file provide only the false sense of protection. - Prevents the private key from being used by unauthorized users to sign code:
IMO this requires user interaction such as entering password or PIN. If you pass the password as a parameter there is always a possibility that other processes would be able to gain it i.e. from process info, logs etc. - Given the private key password is provided by an authorized user, makes the private key for signing by build service:
Cryptographic hardware (smartcard or hsm) accessible via CSP (windows certificate store) with interactively entered PIN should work with signtool without any problems.
I agree that the requirement of user interaction may not be exactly convenient for an automatic build service but you will probably have to choose between secure solution with user interaction and less secure solution without user interaction.
Convenient but less secure solution no. 1: It seems to me that you have already found an acceptable solution because you did not provide any of its disadvantages.
If I abandon my original idea of storing the certificate in the machine store, there is the option of placing the certificate pfx file in an ACL secured folder on the build machine that only the build process and signing users have permissions on. Doing that would allow me to create a build job to use the contained private key while not exposing the file to others that have access to the machine. To use the private key, the build parameters would need to collect the private key password.
However please note that PFX file can be copied undetectably not only from the live system but also from the backups.
Convenient but less secure solution no. 2: Store private key on a smartcard that does not require PIN to be entered and allow system access only to the trusted users. This would ensure that your private key cannot be copied while it would remain easily accessible for signtool. However it would probably require you to have two separate build servers - one without the smartcard accessible to all users and one with the smartcard accessible only to the trusted users.
Inconvenient secure solution: Store private key on a smartcard that requires PIN to be entered and require user interaction (entering of the PIN) during the build process.
You could also consider signing development builds with self-signed codesigning certificate in an automatic mode and signing public release builds with trusted codesigning certificate in manual mode.