How to bootstrap certificates for LCM to reference for signatureverification settings? - powershell

WMF 5.1 includes new functionality to allow signing of MOF documents and DSC Resource modules (reference). However, this seems very difficult to implement in reality -- or I'm making it more complicated than it is...
My scenario is VMs in Azure and I'd like to leverage Azure Automation for Pull DSC Server; however, I see this applying on premise too. The problem is that the certificate used to sign the MOF configurations and/or modules needs to get placed on the machine before fetching and applying the configuration otherwise configuration will fail because the certificate isn't trusted or present on the machine.
I tried using Azure KeyVault to bootstrap the certificate (just the public key because that's my understanding of how signing works) and that fails using Add-AzureRmVMSecret because the CertificateUrl parameter expects a full certificate with the public/private key pair to install. In an ideal world, this would be the solution but that's not the case...
Other ideas, again in this context, would be to upload the cert to blob storage, use a CustomScriptExtension to pull down the cert and install into the LocalMachine store but that feels nasty as well because, ideally, that script should be signed as well and that puts us back in the same spot.
I suppose another idea would be to first PUSH a configuration that downloaded and installed certificates only but that doesn't sound great either.
Last option would be to rely on an AD GPO or something similar to potentially push the certificate first...but, honestly, trying to move away from much of that if/when possible...
Am I off-base on this? It seems like this should be a solvable problem -- just looking for at least one "good" way of doing it.
Thanks

David Jones has quite a bit of experiencing dealing with this issue in an on-premises environment, but as you stated the same concepts should apply for Azure. Here is a link to his blog. This is a link to his GitHub site with a PKITools module that he created. If all else fails you can reach out to him on Twitter.

While it's quite easy to populate a pre-booted image with public certificates. it's not possible (that I have found) to populate the private key.
DSC would require the private key to decrypt the passwords.
The most common tactic people blog about is to use the unattend to script the import of a PFX. issue there is you have to leave the password for the PFX in plain text. Perhaps that is ok in your environment.
The other option requires a more complicated setup. Use a simple DSC or GPO to auto enroll a unique certificate. then have the system, via first boot script or DSC custom resource, tickle an API (Like Polaris) and that triggers a DSC script that uses PKITools or other script to get the public certificate that the machine has. Then have that API push a new DSC config (or pull settings) to the machine.

Related

How to sign correctly a Powershell script for AllSigned ExecutionPolicy?

We have an application where we use several PowerShell scripts. We received a complain regarding about they aren't signed and unable to run them if they have the strictest Execution Policy - AllSigned.
I signed with our certificate issued by well-known issuer via signtool as we do it for dlls and exe app but even after that there is an issue if I try running the script I'm getting warning:
Do you want to run software from this untrusted publisher?
It's signed by a certificate issued by know CA (Sectigo). Only how can I get rid of this warning is to add the certificate to Trusted Publishers. It's not good for customers to do those steps (but maybe it's necessary security step). Note: With the same certificate, we sign exe app and it works fine and Windows doesn't complain. (Look like PowerShell policies are stricter.)
Is it possible somehow avoid getting this warning on a customer side without manually adding our certificate into Trusted Publishers? Looks to me that it is not possible.
What I've found out so far:
I've searched across internet and it looks like there is no solution for that. Even if I used PowerShell script signed by Microsoft Corporation I get the same warning unless I add to the Trusted Publishers folder.
Also e.g. HP directly recommends to add the certificate manually to the cert store.
In a documenation about execution policies is written in AllSigned section: Prompts you before running scripts from publishers that you haven't yet classified as trusted or untrusted.
From those all information, I got it as there is no way how to avoid getting this warning on a customer side without adding to the cert store. I want just to assure myself I'm right.

Getting started with Vault for existing non-containerized Windows apps

We have a bunch of Windows server applications that currently handle secrets as follows; our apps are in C#.
We store them in settings files in code
We store them encrypted, using a certificate
The servers have this certificate with the private key, so they can decrypt the secret
We're looking at implementing Hashicorp Vault. It seems easy enough to simply replace the encrypt-store-decrypt with storing the secret in Vault in the KV engine, and just grabbing it in our apps - that takes that certificate out of the picture entirely. Since we're on-prem, I'll need to figure out our auth method.
We have different apps running on different machines, and it's somewhat dynamic (not as much as an autoscaling scenario, but not permanent - so we can't just assign servers to roles one time and depend on Kerberos auth).
I'm unsure how to make AppRole work in our scenario. We don't have one of the example "trusted platforms" or "trusted entities", there's no Nomad, Chef, Terraform, etc. We have Windows machines, in a domain, and we have a homegrown orchestrator that could be queried to say "This machine name runs these apps", so maybe there's something that can be done there?
Am I in "write your own auth plugin" territory, to speak to our homegrown orchestrator?
Edit - someone on Reddit suggested that this is a simple solution if our apps are all 1-to-1 with the Windows domain account they run under, because then we can just use kerb authentication. That's not currently the way we're architected, but we've got to solve this somehow, and that might do it nicely.
2nd edit - replaced "services" with "apps", since most of our services aren't actually running as Windows services, just processes. The launcher is a Windows service but the individual processes it launches are not.
How about Group Managed Service Accounts?
https://learn.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview
Essentially you created one "trusted platform" (to your key vault service).
Your service can still has its own identity but delegation to the gMSA when you want to retrieve the secrets.
For future visibility, here's what we landed on:
TLS certificate authentication. Using Vault, we issue a handful of certs, each will correspond to a security policy/profile, so that any machine that holds that certificate will be able to authenticate and retrieve the secrets they should have access to.
Kerberos ended up being a dead-end for two reasons. The vault.exe agent (which is part of this use case) can't use the native Windows Kerberos SSPI, so we'd have to manage and distribute keytab files. Also, if we used machine authentication, it would blow up our client count (we're using the cloud-hosted HCP Vault, where pricing is partially based on client count).
Custom plugins can't be loaded into the HCP, of course
Azure won't work, it requires Managed Identities which you can't assign to on-prem machines. Otherwise this might have been a great fit

Can I safely save my private key on public build servers?

This is a technical question on comprehension:
When I want a cloud server (e.g. GitHub Actions, Azure DevOps, or GitLab CI/CD) to build and publish an app to any of the app stores ... isn't it necessary then that I upload my private key to these servers' key vault, so they can sign my app on my behalf?
Isn't that concept a bit risky?
I mean, I was taught to let my private keys never leave my machines.
What if I accidentally misconfigure the security settings on the uploaded key? What if some black hat gets hold of the key and abuses it? I mean, with each build process, the private key is getting copied from the vault to the build runner, usually residing somewhere else.
What are the techniques used to ensure that private keys are kept safely on a public server? Is there an official audit performed on these departments?
Should I rather use different Authenticode certificates for each of the above providers? Or will a single certificate be resilient enough?
I couldn't find a technical discussion on this question, only marketing docs. Has this security concern been scientifically scrutinized?
It is safe to use certificates in Azure DevOps, Azure DevOps encrypts the certificate and then uses it in the build pipeline.
We could use Azure Key Vault to protect encryption keys and secrets like certificates, connection strings, and passwords in the cloud. You could refer this doc for more details.
We could also save the certificate file in the Library->Secure Files, if someone want to access or use it, he need enough permission.
I found some sample to use certificate in the Azure DevOps Service, you could check it.
 
If you are using SSL certificate thumbprint, you could save it in the variable and then set the variable to Secret via the “lock” icon at the end of the row.
If you are using PFX certificate, you could refer to this doc.
Update1
GitHub action
We could save the certificate here in the GitHub, GitHub also encrypts the certificate, we could not get the value after save the variable in the Secrets, and we will get *** when print the Secrets value in the log.

Powershell - automated connection to Power BI service without hardcoding password

We have a PowerShell script to pull Power BI activity data (using Get-PowerBIActivityEvent), and I have been trying to automate it so that it can pull this data daily using an unattended account. The problem is the script must necessarily use the Connect-PowerBIServiceAccount cmdlet, which requires a credential. I don't want to have the passwords hard-coded anywhere (obviously) and ideally don't want to be passing it into the script as a plaintext parameter in case of memory leaks.
I've tried using SSIS as a scheduling mechanism since it allows for encrypted parameters in script tasks, but can't call the PS script with a SecureString parameter since the System.Management.Automation namespace isn't in the GAC (a commandline call wouldn't be possible).
I don't believe task scheduler would offer the functionality needed.
Does anyone know of any elegant ways to connect to the power BI service using encrypted credentials?
In the docs of Connect-PowerBIServiceAccount there are 2 options for unattended sign-in:
Using -Credential, where you pass AAD client ID as username and application secret key as password
Using -CertificateThumbprint and -ApplicationId
For both options you need to configure service pricipal and add proper permissions. I'm not going into details how to configure that, but most probably you'd need (at least) the following application permissions:
I'm not really sure what functionalities you need in the script, but in my experience, majority of the cases can be covered by scheduled task, so the explanation below will apply to that solution.
How you can secure the credentials?
There are variuos possible solutions, depending on your preferences. I'd consider certificate-based authentication as more secure (certificate is available only to current user/all users of the machine).
What's important in certificate-based authentication - make sure that the certificate is available for the account running the script (in many cases it's service account, not your user account).
How can I secure more?
If you want, you can store application ID as secure string (I don't have SSIS to test, so I'm not sure if there's any workaround to make it working in there) or use Export-CliXml. They use Windows Data Protection API (DPAPI), so the file can be decrypted only by the account which was used to encrypt.
To add one more level of security (I'm not even mentioning setting correct access rights to the files as it's obvious) you might put the file in the folder encrypted (you might already have a solution for disk encryption, so use it if you wish).
There are probably some solutions to secure the keys even better, but these ones should do the job. I'm using other Microsoft 365 modules with similar approach (Outlook, SharePoint PnP) and it works quite well.
NOTE: If you need to use user account, instead of service principal, make sure that you have MultiFactor Authentication disabled on that account for that specific application.
The relevant documentation to this (https://learn.microsoft.com/en-us/power-bi/developer/embedded/embed-service-principal) states that admin APIs (i.e. those served via Get-PowerBiActivityEvent) do not currently support service principals. This means it's not currently possible to use a registered app to run these cmdlets unattended.
There is a feature request open to provide this at the moment: https://ideas.powerbi.com/forums/265200-power-bi-ideas/suggestions/39641572-need-service-principle-support-for-admin-api

Powershell certificate authentication on standalone server?

I've tried searching for a solution to this for half a day and decided I need to ask the question myself.
My goal is to remotely control standalone Windows servers via PowerShell on our internal network. Our environment is based on MicroFocus eDirectory instead of MS Active Directory so our servers are not connected via GPOs.
Since PowerShell have existed for such a long time and you can control commandline only installs via this I assumed there would be a solution in a form of certificate authentication client to server but I've yet to find anything resembling this.
I'm aware of workarounds including creating private keys to store decrypt in scripts but we do not want to risk losing such information and wish to be able to create certificates to both new clients and servers without having to include any form of credentials in scripts.
Is there no way to simply use certificates to authenticate in place of credentials?
You should take a look at this chapter in PS remoting book, it describes exactly what you need. https://devopscollective.gitbooks.io/secrets-of-powershell-remoting/content/manuscript/accessing-remote-computers.html
The certificate auth part starts in the middle somewhere, look for "Certificate Authentication"