Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate storing aws profile within the encrypted file / with the key #634

Open
ajvb opened this issue Feb 20, 2020 · 24 comments
Open

Deprecate storing aws profile within the encrypted file / with the key #634

ajvb opened this issue Feb 20, 2020 · 24 comments
Labels
bug enhancement keyservice/awskms priority/medium Medium priority issues (e.g. breaking changes that have a workaround)

Comments

@ajvb
Copy link
Contributor

ajvb commented Feb 20, 2020

There seems to have been a number of issues surrounding our use of AWS profiles:

Storing the AWS Profile in the encrypted file breaks expectations because it cannot be decrypted on systems where that profile doesn't exist. This is very different from how folks are used to interacting with AWS.

I'd propose that we deprecate storing the aws profile within the key and instead require users to pass --aws-profile every time they want to use an AWS profile.

@ajvb ajvb added bug enhancement priority/medium Medium priority issues (e.g. breaking changes that have a workaround) keyservice/awskms labels Feb 20, 2020
@ajvb
Copy link
Contributor Author

ajvb commented Feb 20, 2020

@autrilla What do you think?

@autrilla
Copy link
Contributor

Given all the confusion around it I think we should probably deprecate it, and also deprecate --aws-profile. The AWS lets you use environment variables to control what profile is used, users should just use that.

@pnguyen-okta
Copy link

It's really useful to pass the profile using --aws-profile. I can understand reducing confusion but is it possible to just deprecate storing the aws profile in the encrypted file and keep --aws-profile?

thanks

@ajvb
Copy link
Contributor Author

ajvb commented Feb 20, 2020

I really like how we implemented this in frost: https://github.com/mozilla/frost/blob/master/aws/client.py#L17-L32

You can pass in a profile using --aws-profiles (though for sops it would be --aws-profile) and it gets passed to the session creation, otherwise we just do the default AWS auth flow.

I'd also consider expanding this to removing support for setting AWS roles in the config. Most tools that interact with AWS via the command line require you to authenticate to AWS outside of the context of the tool and it makes sense to me that sops functions the same way. It seems like most of the issues are around people being confused it doesn't work that way (i.e. #555).

@autrilla
Copy link
Contributor

autrilla commented Feb 21, 2020 via email

@jvehent
Copy link
Contributor

jvehent commented Feb 21, 2020

I'd also consider expanding this to removing support for setting AWS roles in the config.

Original support for that came from a requirement to invoke KMS from various accounts transparently, by having Sops assume roles in those accounts. I believe this feature is still in use in our own teams.

@dsalaza4
Copy link

I agree with @jvehent, we use sops in the company I work for and being able to use multiple accounts transparently on the same shell is very important to us. Changing environment variables before running a sops command is pretty dirty, especially in automation scripts.

@autrilla
Copy link
Contributor

I agree with @jvehent, we use sops in the company I work for and being able to use multiple accounts transparently on the same shell is very important to us. Changing environment variables before running a sops command is pretty dirty, especially in automation scripts.

I assume you mean the removal of the feature from the config file.

I personally find it very hard to care about the difference in spelling between:

AWS_PROFILE=foo sops foo.yaml

and

sops --aws-profile=foo foo.yaml

But if there's some specific reason you care about this, I'd love to hear about it.

I'd also consider expanding this to removing support for setting AWS roles in the config.

Original support for that came from a requirement to invoke KMS from various accounts transparently, by having Sops assume roles in those accounts. I believe this feature is still in use in our own teams.

Hm, I wonder if it is? I don't think the .sops.yaml config file is used at all when decrypting or editing. My understanding is that it'll only be used when creating new files. IIRC, I had to change profiles manually back then, but maybe things have changed. I think if you use MFA, SOPS's profile switching is not going to work anyway, because we don't support token input.

@nakatsuchi
Copy link

nakatsuchi commented Feb 26, 2020

I agree with ajvb.
When I decrypt a file encrypted by other member of our team, I have to manually delete profile entry in the file every time.

@casey-robertson
Copy link

One vote to deprecate - it's standard practice in our pipelines and locally to set up the AWS env for each CI/CD step. We've used SOPS for a while now and never touched (maybe never even knew about) embedding the aws_profile in the encrypted file.

@scjudd
Copy link
Contributor

scjudd commented Apr 4, 2020

I'd add that, although the AWS CLI could just pick one of AWS_PROFILE or --profile, it supports both and I've used both. It also seems like SOPS follows this pattern for most other flags/env vars, so I'm not sure why this one should be different.

@brunzefb
Copy link

brunzefb commented Apr 13, 2020

Not having the --aws-profile makes things more difficult for beginners - how do you communicate that the AWS_PROFILE env and AWS_SDK_LOAD_CONFIG=1 are needed? Not having the profile in the encrypted file makes sense.

I initially had expected the aws profile to be settable in the .sops.yaml file -- since you specify the kms id there.

Not specifying the role makes in the .sops.yaml makes sense, I created a policy that allowed access to the sops key. I then assigned the policy to the user. This means, you don't directly have to specify permissions in the key policy.

If you keep the role - then the aws user specified by the AWS_PROFILE must have sts:AssumeRole to be able to use it -- I find this more complicated.

I found the docs to be difficult to use, and had to dig before I got things to work with AWS keys.

  1. Prerequisite -- aws-cli installed, aws configure has run, aws s3 ls --profile myprofile works
  2. You will want to create a new KMS key in the AWS console, assign a policy when creating it to allow admins to use manage and use it.
{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam:::root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::[AWS_ACCOUNT]:user/joe",
                ]
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::[AWS_ACCOUNT]:user/devops",
                    
                ]
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::[AWS_ACCOUNT]:user/devops",
                ]
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}
  1. You need to create an IAM policy, and name it. (you may want to restrict the action a bit more)
{
    "Version": "2012-10-17",
    "Id": "kms-key-policy-sops",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "kms:*",
            "Resource": "arn:aws:kms:us-east-2:[AWS_ACCOUNT]:key/[ID]"
        }
    ]
}
  1. Assign the policy to one or more users (not the ones you gave access to in the key policy -- they already have access)
  2. Switch to a git repo that you want to store secrets in, go to the root folder of repo
  3. Create a new file called .sops.yaml (root of repo) with content
creation_rules:
  - path-regex: '*/**/*'
    kms: 'arn:aws:kms:us-east-2:[AWS_ACCOUNT]:key/[ID]'
  1. Install the sops tool with brew, apt, yum, apk etc.
  2. Export env variables to determine the AWS_PROFILE used. If you are not sure what AWS account the profile (in ~/.aws/credentials the thing in square brackets) is, run aws sts get-caller-identity. This must match the user you assigned the policy to in step 3
export AWS_PROFILE=myprofile
export AWS_SDK_LOAD_CONFIG=1
# instead of doing this you can also invoke sops with
# AWS_PROFILE=myprofile sops ..., but that can be more typing.
  1. You're done.
sops test.yaml # should open vim, change something and exit
cat test.yaml.  # should show encrypted
sops -d test.yaml # should show original unencrypted

It would also be good to have a terraform example to create the key / policy etc, like https://github.com/minamijoyo/terraform-kms-example, so that this can be done in code rather than with the AWS console.

@geota
Copy link

geota commented Jul 14, 2020

This is also an issue with the role that is used to encrypt the secret is being persisted into the encrypted metadata and attempted to always be used in decryption.

SOPS config

creation_rules:
    - kms: 'arn:aws:kms:us-east-1:123456789:key/123456+arn:aws:iam::123456789:role/encrypt-role'

The encryption works fine, but it fails to decrypt because the role is persisted to the enc.yaml metadata file and in the where I am running the decrypt step does not have access to the original role used for encryption (it does have access to the KMS key using a separate role).

Example SOPS encrypted metadata with role hardcoded.

super_secret:
    token: ENC[AES256_GCM,data:asdasdasdasdasdas/wM=,iv:asdasdasdasdasdasd=,tag:asdasdasdasdasdasd==,type:str]
sops:
    kms:
    -   arn: arn:aws:kms:us-east-1:123456789:key/123456
        role: arn:aws:iam::123456789:role/encrypt-role
        created_at: '2020-07-14T18:28:18Z'
        enc: stuff
        aws_profile: ""
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-07-14T18:28:19Z'
    mac: mac-stuff
    pgp: []
    unencrypted_suffix: _unencrypted
    version: 3.5.0

@zhimsel
Copy link

zhimsel commented May 17, 2021

I'd like to voice my opinion on this: please do not deprecate this feature. The "confusion" of needing to have the same profiles as other users is not the responsibility, nor is it relevant, to the SOPS tool. It's a problem to be solved with policy and convention within a team. Removing this feature would force anyone using this tool to follow one very narrow convention.

If you are getting SOPS files with profiles in the file's config, then that's a breakdown of team collaboration, not a break in this tool. If someone is planning on sharing a file with someone (and those people don't use the same profile names), then they should not be using the --profile option... They should be setting their profile via ENV vars (which won't add it to the config) when creating the file to be shared.

I'd like to, as an example, explain my team's use-case for SOPS. We "enforce" specifically-named AWS profiles for anyone working on our codebase. This makes our particular AWS account/IAM design much easier to maintain and implement. So, for our team, we expect and require any humans or machines decrypting the SOPS files to have those profiles present in their config. If the ability to store the profile in any given SOPS file's config is removed, our team would have to use a shim/wrapper around sops to set the correct profile with env vars for a given SOPS file. This would be a step backwards for us. I'm sure there are other users that have similar use-cases or find storing the profile in config is useful or required.

In summary: deprecating this feature would move the burden of enforcing team standards from the teams to this tool.

@autrilla
Copy link
Contributor

@zhimsel thanks a lot for your feedback, it's good to hear from someone from the other side of the argument :)

I agree with what you say, pretty much. If you don't want to store the profile in the SOPS file, why do you even need to tell SOPS about it? I haven't used AWS in a while, but IIRC it's pretty easy to change profiles. Having heard this viewpoint, my stance is that we should document this better, and show users this is probably not what they want to do, but leave --profile be.

@philomory
Copy link

I personally find it very hard to care about the difference in spelling between:

AWS_PROFILE=foo sops foo.yaml

and

sops --aws-profile=foo foo.yaml

But if there's some specific reason you care about this, I'd love to hear about it.

Just to add, being forced to use environment variables instead of the --aws-profile flag would be a bit of a pain for people using SOPS from e.g. Powershell, because Powershell doesn't support inline definition of environment variables that apply to only a single command. Mind, that's more Powershell's problem than SOPS's, but, it's one reason someone might prefer the flag.

@64bit
Copy link

64bit commented Apr 28, 2022

Having aws_profile in the encrypted file has this issue:

In chronological order:

  1. I encrypt a file on local machine using an AWS Profile and other KMS details in .sops.yaml
  2. FluxCD has to decrypt that encrypted file on cluster - even though the IAM role of FluxCD has permissions to use the KMS key - it still cannot decrypt the file because of "aws_profile" key present in encrypted file
  • Decryption on cluster by FluxCD starts working on removing "aws_profile" key from encrypted file.

@hajdukda
Copy link

It's so annoying.. SOPS should work with ANY credentials it finds on the path, and for w/e reason always fails if aws_profile is present, even if you have IRSA or anything else.

@salvadoriume
Copy link

  • Decryption on cluster by FluxCD starts working on removing "aws_profile" key from encrypted file.

Is there any good workaround for this or dirty hacks? I would also vote to do this in native way - the same way is on my side, I encrypt locally with profile and pass it to argoCD (which doesn't know anything about my local profile)

@ashi009
Copy link

ashi009 commented Mar 20, 2024

There is nothing wrong with having profile in the encrypted file. This matches the practice in many other tools, eg. terraform/terragrunt. The problem is with how you use the aws config profiles.

A practice that we found very useful is to name aws profile by access scope instead of the actual role name, and redefine it in different environments. For instance:

For developers:

[profile serviceA]
credential_process = aws configure export-credentials --profile=devops

[profile devops]
sso_start_url = ...

For CI/CD service:

[profile serviceA]
credential_source = Environment

By doing this, the sops yaml will always use aws_profile: serviceA, and getting different credentials on different environments.

@hajdukda
Copy link

hajdukda commented Mar 20, 2024

SOPS does not follow default credentials chain in that case. Which means it works exactly the opposite of many industry standard tools like aws cli or terraform.

@ashi009
Copy link

ashi009 commented Mar 20, 2024

terraform.

This is actually the standard aws sdk behavior, and has nothing to do with individual tool. If you specify profile for the session, it will skip the default cred provider chain entirely.

@hajdukda
Copy link

hajdukda commented May 9, 2024

terraform.

This is actually the standard aws sdk behavior, and has nothing to do with individual tool. If you specify profile for the session, it will skip the default cred provider chain entirely.

We talk here about storing authentication configuration in the sops encrypted file. I might run terraform with AWS_PROFILE exported, but that does not mean it will store the profile in the provider config..

Running sops with the --aws-profile flag will do exactly that - persist the config in the sops encrypted file - it should not do that.. .sops.yaml should store the configuration for authentication method, not the encrypted file...

Another example - encrypting a file with kms key using aws --profile will result in the key information being in the encrypted file, but it will exclude the method used to authenticate to aws api...

@allanger
Copy link

allanger commented Oct 22, 2024

I hope I'm not repeating what has been said already, but I haven't seen it here.

We're using profiles for encryption, and we have a central repo where we are working, all the secrets are stored there and they are encrypted with a KMS key that is available for our Admin AWS profile.

But we also have different organizations, and each organization has its CD runners, and those runners can't have the same access as the Admin profile, so we're adding a second KMS key to each encryption rule, and it's available only for the role assigned to a runner.

That means that our logic looks approximately like that:

- path: ./organization1
  keys:
    - kms: 
      - key: AdminKMS
        aws_profile: ADMIN
      - key: organization1
        aws_profile: ORG_1
- path: ./organization2
  keys:
    - kms: 
      - key: AdminKMS
        aws_profile: ADMIN
      - key: organization2
        aws_profile: ORG_2

Neither --aws-profile nor AWS_PROFILE can work for us, because of SSO configuration. While encrypting/decrypting we need to provide each profile name.

For the local development, having the aws_profile is very convenient, because we can simply run sops without trying to figure out which env vars should be set, etc.

But for the runners, that don't have this concept of profiles, it's not working, and we need to go through all the files and remove the aws_profile property everywhere, then they are not trying to use profiles, and simply using the roles that are assigned to them.

So if I may, I would suggest not removing the aws_profile completely, but instead adding an option not to put it in the encrypted file metadata.

  - path_regex: .*values/organization1/secrets.yaml
    key_groups:
      - kms:
          - arn: SOME_ARN
            aws_profile: ADMIN
          - arn: ANOTHER_ARN
            aws_profile: ORG-1
            aws_profile_persist: false # -- then it's not stored in the metadata, and by default it's true.

This approach would help us working on the secrets without thinking about environment variables and flag, use multiple aws profiles and let runners decrypt secrets without workarounds

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug enhancement keyservice/awskms priority/medium Medium priority issues (e.g. breaking changes that have a workaround)
Projects
None yet
Development

No branches or pull requests