mirror of
https://github.com/getsops/sops.git
synced 2026-02-05 12:45:21 +01:00
Added aws_profile
* Decrypt * Command Line * Master Key * Encrypt * .sops.yaml
This commit is contained in:
28
README.rst
28
README.rst
@@ -273,11 +273,11 @@ Adding and removing keys
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When creating new files, ``sops`` uses the PGP, KMS and GCP KMS defined in the
|
||||
command line arguments ``--kms``, ``--pgp``, ``--gcp-kms`` or ``--azure-kv``, or from
|
||||
the environment variables ``SOPS_KMS_ARN``, ``SOPS_PGP_FP``, ``SOPS_GCP_KMS_IDS``,
|
||||
``SOPS_AZURE_KEYVAULT_URL``. That information is stored in the file under the
|
||||
``sops`` section, such that decrypting files does not require providing those
|
||||
parameters again.
|
||||
command line arguments ``--kms``, ``--aws-profile``, ``--pgp``, ``--gcp-kms`` or
|
||||
``--azure-kv``, or from the environment variables ``SOPS_KMS_ARN``,
|
||||
``SOPS_PGP_FP``, ``SOPS_GCP_KMS_IDS``, ``SOPS_AZURE_KEYVAULT_URL``. That
|
||||
information is stored in the file under the ``sops`` section, such that decrypting
|
||||
files does not require providing those parameters again.
|
||||
|
||||
Master PGP and KMS keys can be added and removed from a ``sops`` file in one of
|
||||
two ways: by using command line flag, or by editing the file directly.
|
||||
@@ -285,8 +285,8 @@ two ways: by using command line flag, or by editing the file directly.
|
||||
Command line flag ``--add-kms``, ``--add-pgp``, ``--add-gcp-kms``, ``--add-azure-kv``,
|
||||
``--rm-kms``, ``--rm-pgp``, ``--rm-gcp-kms`` and ``--rm-azure-kv`` can be used to add
|
||||
and remove keys from a file.
|
||||
These flags use the comma separated syntax as the ``--kms``, ``--pgp``, ``--gcp-kms``
|
||||
and ``--azure-kv`` arguments when creating new files.
|
||||
These flags use the comma separated syntax as the ``--kms``, ``aws-profile``, ``--pgp``,
|
||||
``--gcp-kms`` and ``--azure-kv`` arguments when creating new files.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
@@ -309,6 +309,9 @@ editing:
|
||||
sops:
|
||||
kms:
|
||||
- arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e
|
||||
aws_profile: foo
|
||||
|
||||
If no aws_profile is specified `default` is used for KMS.
|
||||
|
||||
And, similarly, to add a PGP master key, we add its fingerprint:
|
||||
|
||||
@@ -462,11 +465,13 @@ can manage the three sets of configurations for the three types of files:
|
||||
# KMS set A is used
|
||||
- path_regex: \.dev\.yaml$
|
||||
kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod'
|
||||
aws_profile: foo
|
||||
pgp: '1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A'
|
||||
|
||||
# prod files use KMS set B in the PROD IAM
|
||||
- path_regex: \.prod\.yaml$
|
||||
kms: 'arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod,arn:aws:kms:eu-central-1:361527076523:key/cb1fab90-8d17-42a1-a9d8-334968904f94+arn:aws:iam::361527076523:role/hiera-sops-prod'
|
||||
aws_profile: bar
|
||||
pgp: '1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A'
|
||||
|
||||
# gcp files using GCP KMS
|
||||
@@ -485,6 +490,8 @@ found, the filename of the file being created is compared with the filename
|
||||
regexes of the configuration file. The first regex that matches is selected,
|
||||
and its KMS and PGP keys are used to encrypt the file.
|
||||
|
||||
If no aws_profile is specified `default` is used for KMS.
|
||||
|
||||
Creating a new file with the right keys is now as simple as
|
||||
|
||||
.. code:: bash
|
||||
@@ -537,7 +544,9 @@ file ``my_file.yaml``:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ sops groups add --file my_file.yaml --pgp fingerprint1 --pgp fingerprint2 --pgp fingerprint3 --kms arn1 --kms arn2 --kms arn3
|
||||
$ sops groups add --file my_file.yaml --pgp fingerprint1 --pgp fingerprint2 --pgp fingerprint3 --kms arn1 --kms arn2 --kms arn3 --aws-profile bar
|
||||
|
||||
If no aws-profile is specified `default` is used for KMS.
|
||||
|
||||
Or you can delete the 1st group (group number 0, as groups are zero-indexed)
|
||||
from ``my_file.yaml``:
|
||||
@@ -561,6 +570,7 @@ like so:
|
||||
kms:
|
||||
- arn: arn1
|
||||
role: role1
|
||||
aws_profile: foo
|
||||
context:
|
||||
foo: bar
|
||||
- arn: arn2
|
||||
@@ -603,6 +613,7 @@ with ``shamir_threshold``:
|
||||
kms:
|
||||
- arn: arn1
|
||||
role: role1
|
||||
aws_profile: foo
|
||||
context:
|
||||
foo: bar
|
||||
- arn: arn2
|
||||
@@ -870,6 +881,7 @@ encrypt the file, and redirect the output to a destination file.
|
||||
$ export SOPS_KMS_ARN="arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500"
|
||||
$ export SOPS_PGP_FP="C9CAB0AF1165060DB58D6D6B2653B624D620786D"
|
||||
$ sops -e /path/to/existing/file.yaml > /path/to/new/encrypted/file.yaml
|
||||
$ sops --aws-profile foo -e /path/to/existing/file.yaml > /path/to/new/encrypted/file.yaml
|
||||
|
||||
Decrypt the file with ``-d``.
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ func main() {
|
||||
Name: "kms",
|
||||
Usage: "the KMS ARNs the new group should contain. Can be specified more than once",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-profile",
|
||||
Usage: "The single aws profile to use with KMS",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "gcp-kms",
|
||||
Usage: "the GCP KMS Resource ID the new group should contain. Can be specified more than once",
|
||||
@@ -184,6 +188,7 @@ func main() {
|
||||
Action: func(c *cli.Context) error {
|
||||
pgpFps := c.StringSlice("pgp")
|
||||
kmsArns := c.StringSlice("kms")
|
||||
awsProfile := c.String("aws-profile")
|
||||
gcpKmses := c.StringSlice("gcp-kms")
|
||||
azkvs := c.StringSlice("azure-kv")
|
||||
var group sops.KeyGroup
|
||||
@@ -191,7 +196,7 @@ func main() {
|
||||
group = append(group, pgp.NewMasterKeyFromFingerprint(fp))
|
||||
}
|
||||
for _, arn := range kmsArns {
|
||||
group = append(group, kms.NewMasterKeyFromArn(arn, kms.ParseKMSContext(c.String("encryption-context"))))
|
||||
group = append(group, kms.NewMasterKeyFromArn(arn, kms.ParseKMSContext(c.String("encryption-context")), awsProfile))
|
||||
}
|
||||
for _, kms := range gcpKmses {
|
||||
group = append(group, gcpkms.NewMasterKeyFromResourceID(kms))
|
||||
@@ -304,6 +309,10 @@ func main() {
|
||||
Usage: "comma separated list of KMS ARNs",
|
||||
EnvVar: "SOPS_KMS_ARN",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-profile",
|
||||
Usage: "The single aws profile to use with KMS",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "gcp-kms",
|
||||
Usage: "comma separated list of GCP KMS resource IDs",
|
||||
@@ -501,7 +510,7 @@ func main() {
|
||||
if c.Bool("rotate") {
|
||||
var addMasterKeys []keys.MasterKey
|
||||
kmsEncryptionContext := kms.ParseKMSContext(c.String("encryption-context"))
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("add-kms"), kmsEncryptionContext) {
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("add-kms"), kmsEncryptionContext, c.String("aws-profile")) {
|
||||
addMasterKeys = append(addMasterKeys, k)
|
||||
}
|
||||
for _, k := range pgp.MasterKeysFromFingerprintString(c.String("add-pgp")) {
|
||||
@@ -519,7 +528,7 @@ func main() {
|
||||
}
|
||||
|
||||
var rmMasterKeys []keys.MasterKey
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("rm-kms"), kmsEncryptionContext) {
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("rm-kms"), kmsEncryptionContext, c.String("aws-profile")) {
|
||||
rmMasterKeys = append(rmMasterKeys, k)
|
||||
}
|
||||
for _, k := range pgp.MasterKeysFromFingerprintString(c.String("rm-pgp")) {
|
||||
@@ -749,7 +758,10 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) {
|
||||
return nil, common.NewExitError("Invalid KMS encryption context format", codes.ErrorInvalidKMSEncryptionContextFormat)
|
||||
}
|
||||
if c.String("kms") != "" {
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("kms"), kmsEncryptionContext) {
|
||||
|
||||
awsprofile := c.String("aws-profile")
|
||||
|
||||
for _, k := range kms.MasterKeysFromArnString(c.String("kms"), kmsEncryptionContext, awsprofile) {
|
||||
kmsKeys = append(kmsKeys, k)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,9 +75,10 @@ type gcpKmsKey struct {
|
||||
}
|
||||
|
||||
type kmsKey struct {
|
||||
Arn string `yaml:"arn"`
|
||||
Role string `yaml:"role,omitempty"`
|
||||
Context map[string]*string `yaml:"context"`
|
||||
Arn string `yaml:"arn"`
|
||||
Role string `yaml:"role,omitempty"`
|
||||
Context map[string]*string `yaml:"context"`
|
||||
AwsProfile string `yaml:"aws_profile"`
|
||||
}
|
||||
|
||||
type azureKVKey struct {
|
||||
@@ -90,6 +91,7 @@ type creationRule struct {
|
||||
FilenameRegex string `yaml:"filename_regex"`
|
||||
PathRegex string `yaml:"path_regex"`
|
||||
KMS string
|
||||
AwsProfile string `yaml:"aws_profile"`
|
||||
PGP string
|
||||
GCPKMS string `yaml:"gcp_kms"`
|
||||
AzureKeyVault string `yaml:"azure_keyvault"`
|
||||
@@ -175,7 +177,7 @@ func loadForFileFromBytes(confBytes []byte, filePath string, kmsEncryptionContex
|
||||
for _, k := range pgp.MasterKeysFromFingerprintString(rule.PGP) {
|
||||
keyGroup = append(keyGroup, k)
|
||||
}
|
||||
for _, k := range kms.MasterKeysFromArnString(rule.KMS, kmsEncryptionContext) {
|
||||
for _, k := range kms.MasterKeysFromArnString(rule.KMS, kmsEncryptionContext, rule.AwsProfile) {
|
||||
keyGroup = append(keyGroup, k)
|
||||
}
|
||||
for _, k := range gcpkms.MasterKeysFromResourceIDString(rule.GCPKMS) {
|
||||
|
||||
@@ -41,9 +41,10 @@ func KeyFromMasterKey(mk keys.MasterKey) Key {
|
||||
return Key{
|
||||
KeyType: &Key_KmsKey{
|
||||
KmsKey: &KmsKey{
|
||||
Arn: mk.Arn,
|
||||
Role: mk.Role,
|
||||
Context: ctx,
|
||||
Arn: mk.Arn,
|
||||
Role: mk.Role,
|
||||
Context: ctx,
|
||||
AwsProfile: mk.AwsProfile,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -240,9 +240,10 @@ func (m *PgpKey) GetFingerprint() string {
|
||||
}
|
||||
|
||||
type KmsKey struct {
|
||||
Arn string `protobuf:"bytes,1,opt,name=arn" json:"arn,omitempty"`
|
||||
Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"`
|
||||
Context map[string]string `protobuf:"bytes,3,rep,name=context" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Arn string `protobuf:"bytes,1,opt,name=arn" json:"arn,omitempty"`
|
||||
Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"`
|
||||
Context map[string]string `protobuf:"bytes,3,rep,name=context" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile" json:"aws_profile,omitempty"`
|
||||
}
|
||||
|
||||
func (m *KmsKey) Reset() { *m = KmsKey{} }
|
||||
|
||||
@@ -37,6 +37,7 @@ func (ks *Server) encryptWithKms(key *KmsKey, plaintext []byte) ([]byte, error)
|
||||
Arn: key.Arn,
|
||||
Role: key.Role,
|
||||
EncryptionContext: ctx,
|
||||
AwsProfile: key.AwsProfile,
|
||||
}
|
||||
err := kmsKey.Encrypt(plaintext)
|
||||
if err != nil {
|
||||
@@ -85,6 +86,7 @@ func (ks *Server) decryptWithKms(key *KmsKey, ciphertext []byte) ([]byte, error)
|
||||
Arn: key.Arn,
|
||||
Role: key.Role,
|
||||
EncryptionContext: ctx,
|
||||
AwsProfile: key.AwsProfile,
|
||||
}
|
||||
kmsKey.EncryptedKey = string(ciphertext)
|
||||
plaintext, err := kmsKey.Decrypt()
|
||||
|
||||
@@ -42,6 +42,7 @@ type MasterKey struct {
|
||||
EncryptedKey string
|
||||
CreationDate time.Time
|
||||
EncryptionContext map[string]*string
|
||||
AwsProfile string
|
||||
}
|
||||
|
||||
// EncryptedDataKey returns the encrypted data key this master key holds
|
||||
@@ -131,7 +132,7 @@ func NewMasterKey(arn string, role string, context map[string]*string) *MasterKe
|
||||
}
|
||||
|
||||
// NewMasterKeyFromArn takes an ARN string and returns a new MasterKey for that ARN
|
||||
func NewMasterKeyFromArn(arn string, context map[string]*string) *MasterKey {
|
||||
func NewMasterKeyFromArn(arn string, context map[string]*string, awsprofile string) *MasterKey {
|
||||
k := &MasterKey{}
|
||||
arn = strings.Replace(arn, " ", "", -1)
|
||||
roleIndex := strings.Index(arn, "+arn:aws:iam::")
|
||||
@@ -143,17 +144,18 @@ func NewMasterKeyFromArn(arn string, context map[string]*string) *MasterKey {
|
||||
}
|
||||
k.EncryptionContext = context
|
||||
k.CreationDate = time.Now().UTC()
|
||||
k.AwsProfile = awsprofile
|
||||
return k
|
||||
}
|
||||
|
||||
// MasterKeysFromArnString takes a comma separated list of AWS KMS ARNs and returns a slice of new MasterKeys for those ARNs
|
||||
func MasterKeysFromArnString(arn string, context map[string]*string) []*MasterKey {
|
||||
func MasterKeysFromArnString(arn string, context map[string]*string, awsprofile string) []*MasterKey {
|
||||
var keys []*MasterKey
|
||||
if arn == "" {
|
||||
return keys
|
||||
}
|
||||
for _, s := range strings.Split(arn, ",") {
|
||||
keys = append(keys, NewMasterKeyFromArn(s, context))
|
||||
keys = append(keys, NewMasterKeyFromArn(s, context, awsprofile))
|
||||
}
|
||||
return keys
|
||||
}
|
||||
@@ -185,7 +187,7 @@ func (key MasterKey) createSession() (*session.Session, error) {
|
||||
if matches == nil {
|
||||
return nil, fmt.Errorf("No valid ARN found in %q", key.Arn)
|
||||
}
|
||||
config := aws.Config{Region: aws.String(matches[1])}
|
||||
config := aws.Config{Region: aws.String(matches[1]), Credentials: credentials.NewSharedCredentials("", key.AwsProfile)}
|
||||
opts := session.Options{
|
||||
Config: config,
|
||||
AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestKMS(t *testing.T) {
|
||||
|
||||
func TestKMSKeySourceFromString(t *testing.T) {
|
||||
s := "arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e+arn:aws:iam::927034868273:role/sops-dev, arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d"
|
||||
ks := MasterKeysFromArnString(s, nil)
|
||||
ks := MasterKeysFromArnString(s, nil, "foo")
|
||||
k1 := ks[0]
|
||||
k2 := ks[1]
|
||||
expectedArn1 := "arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e"
|
||||
|
||||
@@ -67,6 +67,7 @@ type kmskey struct {
|
||||
Context map[string]*string `yaml:"context,omitempty" json:"context,omitempty"`
|
||||
CreatedAt string `yaml:"created_at" json:"created_at"`
|
||||
EncryptedDataKey string `yaml:"enc" json:"enc"`
|
||||
AwsProfile string `yaml:"aws_profile" json:"aws_profile"`
|
||||
}
|
||||
|
||||
type gcpkmskey struct {
|
||||
@@ -135,6 +136,7 @@ func kmsKeysFromGroup(group sops.KeyGroup) (keys []kmskey) {
|
||||
EncryptedDataKey: key.EncryptedKey,
|
||||
Context: key.EncryptionContext,
|
||||
Role: key.Role,
|
||||
AwsProfile: key.AwsProfile,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -265,6 +267,7 @@ func (kmsKey *kmskey) toInternal() (*kms.MasterKey, error) {
|
||||
EncryptedKey: kmsKey.EncryptedDataKey,
|
||||
CreationDate: creationDate,
|
||||
Arn: kmsKey.Arn,
|
||||
AwsProfile: kmsKey.AwsProfile,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user