-
Notifications
You must be signed in to change notification settings - Fork 10
feat: add SOPS for secrets #6
Description
Add support for SOPS secrets.
https://github.com/getsops/sops
Currently haloy supports only secrets with 1password. I worked already alot with sops and would like to add this feature into haloy.
SOPS files can have multiple formats. E.g. yaml, json and also dotenv. I would like to support all of them.
In the past I used https://github.com/dbsystel/cdk-sops-secrets.
Idea
Think about something like this:
secret_providers:
sops:
development:
file: ./secrets.dev.env
env:
- name: CLIENT_ID
from:
secret: sops:development.CLIENT_ID
- name: CLIENT_SECRET
from:
secret: sops:development.CLIENT_SECRETSops encypted secrets.dev.env
{
"data": "ENC[AES256_GCM,data:vcqWg4azs9RdQY8dywNmnYDTBLctM45K4S5kvILowWwZZB7bSFN+v6TfNTRpN04jGFM=,iv:TWfGfAbB0X+oWFNsNJ4taU+am01bS6u54CAMUove6rs=,tag:/Cv2w/ZPbkmE1vGDD1ujrQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age15ce8f74ehcm7qckew5cerdrjp3xnz7rs2fcqpp86ghrlrhsww95qxtu22x",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNSGVlQUIwNDZoVDZLMXRJ\na2dKVkR0WGZJZU5DWTllMHd5aFUvdzc2MmdjCnJ6MEEzNERsMFRiYWNrdFdWQmtT\ndDd2WU5ZM3NWWUswdXl2SmtIcjZDRjgKLS0tIC9pRlBHald3aXJOY3BxcmhrcVJ3\ndjVDWk9LNllPSTlXRUVSU3dNcGNsSXMKByfwoeIe7ENkWbJFsdS/+/1zjRhOyvwZ\n/hPHht7TU/Iy9S4PXW/dsosav9yGp4YOwrZIcHEdz66A33j4MQJAmA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2026-03-30T11:42:11Z",
"mac": "ENC[AES256_GCM,data:/up6MNZcn7q7WIWgql/WzztTi472CarJ2t8DtMGco6DlRGGHxx4y71tUxXOulTxGCrrbooLzblVspc5mEtHqIMEZnbsOdNYdqzLgMa5CAjMWejQeMNIEzT191lV+4CeBMBOPBj0AX49jz4GTJAT4cwE/jE6AR0mXCScud4b0vxo=,iv:p4qRbuq/96iQPHE4MyYOQFFdOoqoAFRIEv4S2nNS8/o=,tag:3WfRypwjNo80OPctnP8RIg==,type:str]",
"version": "3.12.2"
}
}For json/yaml secrets you could do something like this:
secret_providers:
sops:
development:
file: ./secrets.dev.yaml
env:
- name: CLIENT_ID
from:
secret: sops:development.client.id
- name: CLIENT_SECRET
from:
secret: sops:development.client.secretSops nested yaml
client:
id: ENC[AES256_GCM,data:RiEi,iv:TfEnebGEcqykXZW81snYiYU/0dBij6Zqo08/2G6LEjY=,tag:QHHsHI/FPbXAIhoKgJW7RA==,type:str]
secret: ENC[AES256_GCM,data:Tb70,iv:yA6zN07pSMTJe3ParrgWFhXRC239TOT5eIO2A9bHtY0=,tag:0qr6ukfpt9II/HenhllRCg==,type:str]
foo_unencrypted:
text: foo
sops:
age:
- recipient: age15ce8f74ehcm7qckew5cerdrjp3xnz7rs2fcqpp86ghrlrhsww95qxtu22x
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIWlpEeVU3dTlsYWhGT2pI
VnY0T21vMWxORUpyTkhFQTdNdXlmUW51U0VvCldCaHZxaktDZEFITU02Tjhmc2hk
d3psWkYrVUZsRytBTm1uMUVXckh3YzQKLS0tIEhxdmFwMno0VjhFOXNRU05wbHlF
a21HcHFuQU1CajhZZjZWRXRKazJqQmcKPzuCI5uqIv2lopoJpwFyCkImHAcVWf6k
cfBXCxx9gFnFxNgzgxyC5Ua+XeIf7LsOy3OF8q1N0zBwpN0ox7zq/g==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-03-30T11:46:40Z"
mac: ENC[AES256_GCM,data:b3ll2qfFtiO+zW5ZMRN8fp3vqWjCUS208NtiX1ah+dMuJa8jG8IQVzuJdf+zEvICsdnsNLCmFia0xZfurGulJOHQ0FUIYaWgtyJkQabVV2hr9aTa7M8xRmA06c7xJWStSUVQ2vcVkRuVy++EjpXRSTGF6W/v/xH6SyEpTdRiZrY=,iv:6jdJSNltcLA2+YazbL0b3gW1xNZiGb3SDGmUWFoRDVE=,tag:PNbUMBqmT/Dq54Mg/37owg==,type:str]
unencrypted_suffix: _unencrypted
version: 3.12.2Probably it is a good idea to make a breaking change on the .-notation.
Instead of secret: sops:development.client.id you could have secret: sops:development:client.id.
Changes
- Adding SOPSSourceConfig with
FileandFormattosecret_providers.go - Adding
provider_sops.gowithfetchFromSOPS - Adding
sopsprovider toresolve_secrets.go
Since SOPS is written in Go, this could be a first-class feature via "github.com/getsops/sops/v3/decrypt".
We need to resolve the path for ResolveSecrets relative to the config file's location.
In this case, every call to ResolveSecrets would need to receive the configPath.