1
0
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:
Mark Kelly
2019-01-11 14:40:28 +00:00
parent 5b48aa34f2
commit 7605dd76b1
9 changed files with 62 additions and 27 deletions

View File

@@ -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``.

View File

@@ -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)
}
}

View File

@@ -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) {

View File

@@ -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,
},
},
}

View File

@@ -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{} }

View File

@@ -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()

View File

@@ -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,

View File

@@ -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"

View File

@@ -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
}