Storing credentials in plain text is generally considered a bad idea. But chances are, if you work in DevOps, you have a few credential files on your system. Or perhaps you store your secrets as environment variables.
A significant vector in supply chain attacks leverages credential stealing malware to gain access to your development pipeline. Keeping your secrets in a "protected by default" mode significantly reduces the likelihood of a successful attack.
CYA aims to protect the config files and environment variables you use. It does
so by encrypting the files and environment variable values you want to protect.
Then you can simply encrypt and decrypt using Protect-CyaConfig
and
Unprotect-CyaConfig
.
CYA also helps you manage different credentials for different environments.
PS > New-CyaConfig AWSTest
[...]
PS > New-CyaConfig AWSProd
[...]
PS > Unprotect-CyaConfig AWSTest
Enter password for CyaPassword "Default": *********
Install-Module CYA
Once installed the following functions are exported and available.
- New-CyaConfig
- Get-CyaConfig
- Protect-CyaConfig (alias pcya)
- Unprotect-CyaConfig (alias ucya)
- Rename-CyaConfig
- Remove-CyaConfig
- New-CyaPassword
- Get-CyaPassword
- Rename-CyaPassword
- Remove-CyaPassword
CYA makes protecting environment variables easy. One big problem with secrets
as environment variables is setting them without exposing them in your command
history. CYA accomplishes this by using PowerShell's Read-Host -AsSecureString
To create a new CyaConfig use New-CyaConfig
and follow the prompts.
PS > New-CyaConfig
cmdlet New-CyaConfig at command pipeline position 1
Supply values for the following parameters:
Name: sample
WARNING: CyaPassword "Default" not found, creating now with New-CyaPassword.
Enter new password: ********
Confirm new password: ********
Config type
[E] EnvVar [F] File [?] Help (default is "E"):
Variable 1 name (Enter when done): MYVAR
MYVAR value: *****
Variable 2 name (Enter when done): MYOTHERVAR
MYOTHERVAR value: *****
Variable 3 name (Enter when done):
Name : sample
Type : EnvVar
CyaPassword : Default
ProtectOnExit : True
Item : MYVAR
Status : Protected
Name : sample
Type : EnvVar
CyaPassword : Default
ProtectOnExit : True
Item : MYOTHERVAR
Status : Protected
You can configure CYA to automatically delete unencrypted files when you exit
PowerShell by setting the -ProtectOnExit
parameter to $True
. When you exit
PowerShell, or remove the Module, the file will be deleted. Keep in mind, you
have to exit cleanly using the exit
command or ctrl + d
(Linux) for this to
work.
PS > Get-ChildItem | New-CyaConfig -Name sample -ProtectOnExit $true
Enter password for CyaPassword "Default": ********
Name : sample
Type : File
CyaPassword : Default
ProtectOnExit : True
Item : C:\Users\nickadam\sample\file1.conf
Status : Unprotected
Name : sample
Type : File
CyaPassword : Default
ProtectOnExit : True
Item : C:\Users\nickadam\sample\file2.json
Status : Unprotected
Protect (delete) and unprotect (decrypt) your secrets.
Unprotect-CyaConfig
[... do what you need to do ...]
Protect-CyaConfig
The aliases ucya
and pcya
are available for convenience.
ucya
[... do what you need to do ...]
pcya
CYA presents a warning if any config items are unprotected when the CYA module
loads. You can choose to see this warning every time you open a shell by adding
Import-Module CYA
to your PowerShell Profile.
You can also suppress these warnings by setting the environment variable
CYA_DISABLE_UNPROTECTED_MESSAGE
to $True
.
CYA supports using different passwords on different CyaConfigs using the
-CyaPassword
parameter. The New-CyaConfig
and New-CyaPassword
functions
use "Default" by default.
CyaConfigs and CyaPasswords are encrypted using AES-256-CBC and can be moved to any system. Your password is all that's needed to decrypt (so make it a good one).
The contents of files and environment variable values are validated using a salted
SHA256 hash. If you unprotect a file and modify it, the file's hash will no longer
match the hash stored in the config. CYA will not delete the file and will
instead show a warning that the file path conflicts. If you wish to protect a
modified file, use New-CyaConfig
again.
By Default CYA will store configs, passwords, and encrypted files in a .cya
folder in your $Home
(~
). You can change this location to wherever you like
by setting the environment variable CYAPATH
to you desired location. You may
want to use a cloud synced folder or any location that you can backup. Or you
can just backup the defualt .cya
folder.
The .cya
folder contains three subfolders:
configs
stores the configs, either EnvVar (environment variable) or File.passwords
stores the encrypted keys to the configs you decrypt with your password.bins
stores the encrypted files
Configs and Passwords in CYA are largely immutable but that doesn't mean you can't change things. For example, if you want to change your password, you can follow these steps to create a new CyaPassword, new CyaConfig, and remove the old.
Rename-CyaPassword -Name Default -NewName OldDefault
Rename-CyaConfig -Name MyConfig -NewName OldMyConfig
New-CyaPassword -Name Default
Unprotect-CyaConfig -Name OldMyConfig
New-CyaConfig -Name MyConfig -CyaPassword Default
[... Add the files or environment variables from OldMyConfig ...]
Protect-CyaConfig MyConfig
Remove-CyaConfig -Name OldMyConfig
Remove-CyaPassword -Name OldDefault
Or, if you're comfortable, you could make some trivial changes to the config files directly, they are just JSON files. Changing the path to a file, or name of a variable won't break anything.
Help documentation is available for each function in CYA.
Help New-CyaConfig
Tests are written in the pester test framework.
Install-Module pester
git clone https://github.com/nickadam/powershell-cya.git
cd powershell-cya
Invoke-Pester
Install-Module PSScriptAnalyzer
Invoke-ScriptAnalyzer -Recurse .\CYA\
Install ReportGenerator.
Find-Package ReportGenerator -ProviderName "nuget" -Source "https://nuget.org/api/v2" | Install-Package -Scope CurrentUser
Identify the location of the relevant ReportGenerator.exe. In my case:
$RG="$LOCALAPPDATA\PackageManagement\NuGet\Packages\ReportGenerator.5.0.4\tools\net6.0\ReportGenerator.exe"
Generate a coverage.xml
file with pester.
Invoke-Pester -CodeCoverage ".\CYA\*" -CodeCoverageOutputFileFormat JaCoCo
Generate code coverage report pages.
& $RG -reports:coverage.xml -targetdir:.\Coverage -sourcedirs:.\CYA
Review the beautiful report.
start .\Coverage\index.html