packages feed

dhall-secret 0.5.50 → 0.5.52

raw patch · 11 files changed

+369/−3 lines, 11 files

Files

+ README.md view
@@ -0,0 +1,188 @@+# dhall-secret+[![Build and Test](https://github.com/jcouyang/dhall-secret/actions/workflows/build.yml/badge.svg)](https://github.com/jcouyang/dhall-secret/actions/workflows/build.yml)++A simple tool to manage secrets in Dhall configuration, inspired by [sops](https://github.com/mozilla/sops)++## Install+### nix+```+nix-env -f https://github.com/jcouyang/dhall-secret/archive/master.tar.gz -iA dhall-secret.components.exes.dhall-secret+```++### binary+Download binary according to your OS from [releases channel](https://github.com/jcouyang/dhall-secret/releases)++### docker+docker images are avail [here](https://github.com/jcouyang/dhall-secret/pkgs/container/dhall-secret)+```+docker run ghcr.io/jcouyang/dhall-secret:latest+```++## Usage++```+Usage: dhall-secret (encrypt | decrypt | gen-types) [-v|--version]++Available options:+-h,--help                Show this help text+-v,--version             print version++Available commands:+encrypt                  Encrypt a Dhall expression+decrypt                  Decrypt a Dhall expression+gen-types                generate types+```++## Example+create a unencrypted version of Dhall file `./test/example.dhall`, put the plain text secret in `PlainText`+```dhall+let empty =+      https://prelude.dhall-lang.org/Map/empty++in  { kmsExample =+        dhall-secret.AwsKmsDecrypted+          { KeyId = "alias/dhall-secret/test"+          , PlainText = "a-secret"+          , EncryptionContext = empty Text Text+          }+    , ageSecret =+        dhall-secret.AgeDecrypted+          { Recipients =+            [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp"+            , "age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"+            ]+          , PlainText = "another-secret"+          }+    , somethingElse = "not-secret"+    }++```++The file contains two secrets to be encrypted+- `a-secret` is `dhall-secret.AwsKmsDecrypted` needs to be encrypted via KMS with key id `alias/dhall-secret/test`+- `another-secret` is a `dhall-secret.AgeDecrypted` needs to be encrypted via Age, only who from `Recipients` can decrypt the message.+- `not-a-secret` won't be encrypted++### AWS KMS++1. login to your AWS account, either through `~/.aws/credentials` or `AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY` environment++2. probably need to also `export AWS_REGION=<your-kms-key-region>`++### Age++You will need to export AGE-SECRET-KEY to `DHALL_SECRET_AGE_KEYS` env to decrypt a dhall+```+export DHALL_SECRET_AGE_KEYS=AGE-SECRET-KEY-1GLAZ75TDSSR647WXD0MH3RUU8XGRK6R5SD8UGQ6C6R9MCYR03ULQSUC7D6+dhall-secret decrypt -f ./test/example02.encrypted.dhall+```++or export multiple keys in multiple lines+```+export DHALL_SECRET_AGE_KEYS="AGE-SECRET-KEY-1HKC2ZRPFFY66049G5EWYLT2PMYKTPN6UW6RFEEEN3JEEWTFFFDNQ2QTC8M+AGE-SECRET-KEY-1GLAZ75TDSSR647WXD0MH3RUU8XGRK6R5SD8UGQ6C6R9MCYR03ULQSUC7D6"+dhall-secret decrypt -f ./test/example02.encrypted.dhall+```++you don't need to have the secret key to encrypt the file.++### Encrypt+#### from stdin to stdout+```+> dhall-secret encrypt+dhall-secret.AgeDecrypted+  { Recipients =+    [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp" ]+    , PlainText = "hello age!"+  }+[Ctrl-D]+let dhall-secret =+      https://raw.githubusercontent.com/jcouyang/dhall-secret/master/Type.dhall+        sha256:d7b55a2f433e19cf623d58c339346a604d96989f60cffdecee125a504a068dc9++in  dhall-secret.AgeEncrypted+      { Recipients =+        [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp" ]+      , CiphertextBlob =+          ''+          -----BEGIN AGE ENCRYPTED FILE-----+          YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEUHJPRnJzV2JVL2VKTDE3+          VFpOVFZqOHhIMlhsNCtrNjQ4ZU95cjQ1T25rCk42cFBjcVRUV3ZZYkd0dUxBakN6+          YVNzY1k5WEtNRUJNbjI5YUs3RThlQWcKLS0tIHNObWFIZW9MR2FsekQwY0dyZ3hF+          VmdVYzVGRDRDUWFzWTN3N3RGRWVCbG8KSwwDZ5d+O1w0U8AQB4TRdbA7V20dk2kk+          5P1QNjxYMEyHyJKiijRyltq++          -----END AGE ENCRYPTED FILE-----+          ''+      }+```++#### encrypt file in place+```+dhall-secret encrypt -f test/example.dhall --inplace+```+#### to a new file+```+dhall-secret encrypt -f test/example.dhall -o test/example.encrypted.dhall+```+#### update a encrypted file+you can update a encrypted file with dhall expr without needing to decrypt the file+```+dhall-secret encrypt <<< './test/example02.dhall with plain = dhall.AgeDecrypted {PlainText = "not plain any more", Recipients = ["age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"]}'+```++### Decrypt+#### to stdout+```+> dhall-secret decrypt -f test/example.encrypted.dhall+let dhall-secret = ...+in  { aesExample =+        dhall-secret.Aes256Decrypted+          { KeyEnvName = "MY_AES_SECRET"+          , PlainText = "another secret to be encrypted"+          }+    , kmsExample =+        dhall-secret.AwsKmsDecrypted+          { KeyId =+              "arn:aws:kms:ap-southeast-2:930712508576:key/5d2e1d54-c2e6-49a8-924d-bed828e792ed"+          , PlainText = "a secret to be encrypted"+          , EncryptionContext = [] : List { mapKey : Text, mapValue : Text }+          }+    , somethingElse = "not secret"+    }+```+#### in place+```+dhall-secret decrypt -f test/example.encrypted.dhall --inplace+```+#### to a new file+```+dhall-secret decrypt -f test/example.encrypted.dhall -o test/example.dhall+```+#### plaintext+`--plain-text` will output dhall without types+```+> dhall-secret decrypt -f ./test/example02.encrypted.dhall -p+{ foo =+  { ageSecret =+      dhall-secret.AgeDecrypted+        { Recipients =+          [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp"+          , "age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"+          ]+        , PlainText = "hello age!"+        }+  , plain = "hello world"+  }+}+```+it is very useful when you want to convert it to yaml/json+```+dhall-secret decrypt -f ./test/example02.encrypted.dhall -p | dhall-to-yaml+foo:+  ageSecret: "hello age!"+  plain: hello world+```+### Re-encrypt+```+dhall-secret decrypt -f test/example.encrypted.dhall | dhall-secret encrypt --in-place+```
dhall-secret.cabal view
@@ -20,7 +20,7 @@ -- PVP summary:     +-+------- breaking API changes --                  | | +----- non-breaking API additions --                  | | | +--- code changes with no API change-version:            0.5.50+version:            0.5.52  -- A short (one-line) description of the package. synopsis:           Encrypt Decrypt Dhall expressions@@ -31,7 +31,7 @@ homepage:           https://github.com/jcouyang/dhall-secret  -- The license under which the package is released.-license:            Apache-2.0+license:            BSD-3-Clause  -- The file containing the license text. license-file:       LICENSE@@ -48,7 +48,11 @@ build-type:         Simple  -- Extra source files to be distributed with the package, such as examples, or a tutorial module.--- extra-source-files:+extra-source-files:+        README.md+        src/Type.dhall+        test/*.key+        test/*.dhall source-repository head   type: git   location: https://github.com/jcouyang/dhall-secret
+ src/Type.dhall view
@@ -0,0 +1,13 @@+< AgeDecrypted : { PlainText : Text, Recipients : List Text }+| AgeEncrypted : { CiphertextBlob : Text, Recipients : List Text }+| AwsKmsDecrypted :+    { EncryptionContext : List { mapKey : Text, mapValue : Text }+    , KeyId : Text+    , PlainText : Text+    }+| AwsKmsEncrypted :+    { CiphertextBlob : Text+    , EncryptionContext : List { mapKey : Text, mapValue : Text }+    , KeyId : Text+    }+>
+ test/example.dhall view
@@ -0,0 +1,22 @@+let dhall-secret =+      https://raw.githubusercontent.com/jcouyang/dhall-secret/38fc27c7da185dda1ddae67c389080154c2336fc/Type.dhall++let empty =+      https://raw.githubusercontent.com/dhall-lang/dhall-lang/v22.0.0/Prelude/Map/empty.dhall++in  { kmsExample =+        dhall-secret.AwsKmsDecrypted+          { KeyId = "alias/dhall-secret/test"+          , PlainText = "a secret to be encrypted"+          , EncryptionContext = empty Text Text+          }+    , ageSecret =+        dhall-secret.AgeDecrypted+          { Recipients =+            [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp"+            , "age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"+            ]+          , PlainText = "hello age!"+          }+    , somethingElse = "not secret"+    }
+ test/example01.dhall view
@@ -0,0 +1,23 @@+let T = ./Type.dhall++let empty =+      https://raw.githubusercontent.com/dhall-lang/dhall-lang/v22.0.0/Prelude/Map/empty.dhall++in  { foo =+      { aws =+        { noContext =+            T.AwsKmsDecrypted+              { KeyId = "alias/dhall-secret/test"+              , PlainText = "hello kms"+              , EncryptionContext = empty Text Text+              }+        , withContext =+            T.AwsKmsDecrypted+              { KeyId = "alias/dhall-secret/test"+              , PlainText = "hello kms with context"+              , EncryptionContext = toMap { crew = "bar", environment = "prod" }+              }+        }+      , plain = "hello world"+      }+    }
+ test/example01.expected.dhall view
@@ -0,0 +1,39 @@+let dhall-secret =+      < Aes256Decrypted : { KeyEnvName : Text, PlainText : Text }+      | Aes256Encrypted :+          { CiphertextBlob : Text, IV : Text, KeyEnvName : Text }+      | AwsKmsDecrypted :+          { EncryptionContext : List { mapKey : Text, mapValue : Text }+          , KeyId : Text+          , PlainText : Text+          }+      | AwsKmsEncrypted :+          { CiphertextBlob : Text+          , EncryptionContext : List { mapKey : Text, mapValue : Text }+          , KeyId : Text+          }+      >++in  { foo =+      { aws =+        { noContext =+            dhall-secret.AwsKmsDecrypted+              { KeyId =+                  "arn:aws:kms:ap-southeast-2:930712508576:key/5d2e1d54-c2e6-49a8-924d-bed828e792ed"+              , PlainText = "hello kms"+              , EncryptionContext = [] : List { mapKey : Text, mapValue : Text }+              }+        , withContext =+            dhall-secret.AwsKmsDecrypted+              { KeyId =+                  "arn:aws:kms:ap-southeast-2:930712508576:key/5d2e1d54-c2e6-49a8-924d-bed828e792ed"+              , PlainText = "hello kms with context"+              , EncryptionContext =+                [ { mapKey = "crew", mapValue = "bar" }+                , { mapKey = "environment", mapValue = "prod" }+                ]+              }+        }+      , plain = "hello world"+      }+    }
+ test/example02.dhall view
@@ -0,0 +1,14 @@+let T = https://oyanglul.us/dhall-secret/Type.dhall++in  { foo =+      { ageSecret =+          T.AgeDecrypted+            { Recipients =+              [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp"+              , "age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"+              ]+            , PlainText = "hello age!"+            }+      , plain = "hello world"+      }+    }
+ test/example02.encrypted.dhall view
@@ -0,0 +1,27 @@+let dhall-secret =+      https://raw.githubusercontent.com/jcouyang/dhall-secret/master/Type.dhall+        sha256:d7b55a2f433e19cf623d58c339346a604d96989f60cffdecee125a504a068dc9++in  { foo =+      { ageSecret =+          dhall-secret.AgeEncrypted+            { Recipients =+              [ "age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp"+              , "age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y"+              ]+            , CiphertextBlob =+                ''+                -----BEGIN AGE ENCRYPTED FILE-----+                YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBINUtOMnJzMFdyZXhnSUEr+                UGcyUlBuQ1pqdDRvTUtEYUVnS0FGR25HOWpJClFKVlNEeTBkZGJFUjAyNHJJMlRs+                M1VjN1FBclc4Qmh0M2kvRE9lV0JoZWcKLT4gWDI1NTE5IEc0ejJxclZFRmI2cWww+                Q0Ztc3VoK2FyYVNweXJWUURoWHVxN0ZNSHZ3UUEKUVUyT3NsRFN4MG4zaENITVNv+                OFhwaHk0cnRLK0RlaldYR25DYXpSZkVzcwotLS0gVlpPVGNHRnlZbU5mTWJHZ0Uz+                RmFTZmt0K0JZN3ZiNU0yRTNoVlpFOG03awrR//vOiCopVyEUXXrhiWDepXO4Ji8L+                E4nBuypVhk/xOWSTnNP0isKElAg=+                -----END AGE ENCRYPTED FILE-----+                ''+            }+      , plain = "hello world"+      }+    }
+ test/example02.expected.dhall view
@@ -0,0 +1,30 @@+let dhall-secret =+      < Aes256Decrypted :+          { Context : Text, KeyEnvName : Text, PlainText : Text }+      | Aes256Encrypted :+          { CiphertextBlob : Text+          , Context : Text+          , KeyEnvName : Text+          , Nonce : Text+          , Salt : Text+          , Tag : Text+          }+      | AwsKmsDecrypted :+          { EncryptionContext : List { mapKey : Text, mapValue : Text }+          , KeyId : Text+          , PlainText : Text+          }+      | AwsKmsEncrypted :+          { CiphertextBlob : Text+          , EncryptionContext : List { mapKey : Text, mapValue : Text }+          , KeyId : Text+          }+      >++in  { foo =+      { aes256 =+          dhall-secret.Aes256Decrypted+            { KeyEnvName = "MY_AES_SECRET", PlainText = "hello AES" }+      , plain = "hello world"+      }+    }
+ test/example02.test.key view
@@ -0,0 +1,3 @@+# created: 2022-10-17T18:48:15+11:00+# public key: age1rl8j26etwulmav6yn8p4huu6944n7hsr2pyu2dr0evjzsj2tq92q48arjp+AGE-SECRET-KEY-1GLAZ75TDSSR647WXD0MH3RUU8XGRK6R5SD8UGQ6C6R9MCYR03ULQSUC7D6
+ test/example02.test2.key view
@@ -0,0 +1,3 @@+# created: 2022-10-17T18:48:55+11:00+# public key: age1xmcwr5gpzkaxdwz2udww7lht2j4evp4vpl0ujeu64pe5ncpsk9zqhkfw5y+AGE-SECRET-KEY-1HKC2ZRPFFY66049G5EWYLT2PMYKTPN6UW6RFEEEN3JEEWTFFFDNQ2QTC8M