diff --git a/README.rst b/README.rst index 02c15ce1f..a7c18a88a 100644 --- a/README.rst +++ b/README.rst @@ -11,8 +11,8 @@ SOPS: Secrets OPerationS .. sectnum:: .. contents:: Table of Contents -Requirements ------------- +Up and running in 60 seconds +---------------------------- First install some libraries from your package manager: * RHEL family:: @@ -32,10 +32,15 @@ Then install `sops` from pip:: sudo pip install --upgrade sops -note: on centos/sl, you may need to upgrade `botocore` after installing -sops to deal with a `requirement conflict -`_. -Do so with `sudo pip install -U botocore`. +Clone the repository, load the test PGP key and open the test files:: + + $ git clone https://github.com/mozilla/sops.git + $ cd sops + $ gpg --import tests/sops_functional_tests_key.asc + $ sops example.yaml + +This last step will decrypt `example.yaml` using the test private key. To create +your own secrets files using keys under your control, keep reading. Usage ----- diff --git a/example.json b/example.json index 006b09640..fa300e070 100644 --- a/example.json +++ b/example.json @@ -1,7 +1,7 @@ { "firstName": "ENC[AES256_GCM,data:Sf9dCw==,iv:OtsxqCFAvsDfiUIu+FmMT+9SZZ+hwFXxWAoA/fFt4n0=,tag:UJpAMAlrLm+TMIAkQCShTg==,type:str]", "lastName": "ENC[AES256_GCM,data:8CSE1Fc=,iv:ZwNczZao5fK44uYH+TU+RwXSC6OHjbBWCrQiO97Ws3I=,tag:ghRiOGqNPvotGEIE80XpRg==,type:str]", - "age": "ENC[AES256_GCM,data:hXI=,iv:er2l2sivl6Q00VwfF/YTOSs19q3AYqwVCSdBZkUZ9cc=,tag:U9IQcgO8nRdZGKuk/GaB+w==,type:int]", + "age": "ENC[AES256_GCM,data:UHBRAg==,iv:79skTitX1Tq8EtiyAYeP6Ir8dAkiporJGSHqRThHh5g=,tag:NhZfAZs64lX/+HtePiOkww==,type:float]", "address": { "city": "ENC[AES256_GCM,data:DKo/DSI8QjU=,iv:ZVT8sB8Lq7Q1l4kRmEpjq78BLXL6VSG5Wl+s0skKz9k=,tag:VQ8t+CtkTd6l20wrQHECPA==,type:str]", "postalCode": "ENC[AES256_GCM,data:DxjkWjslhRKFeA==,iv:jZYRetIj1Brxj0Dhc6e06NOwQt4nR0wW6iVRN/n5SwI=,tag:L2fq3kQuNyJ04nGGPpJV9Q==,type:str]", @@ -19,8 +19,8 @@ } ], "sops": { - "mac": "ENC[AES256_GCM,data:2ffgLOYXFoMS7ECteIOWzV0iyHa316sxCXN5Ms4nDYrMpOADf+l3xLYXO6UZa/LIhI2LcQaDplFv3ukrJ2Zrr1vntz52E+MDV2xwetY1/QioFM2GHCfG33vbL6PEoi2lUKlUyIj+3UejV1hY9B4xDVIkXP6b1I7IwPi9wqYCx0g=,iv:4vlcBtZ5iI/0WVes0ZDvenBToEXthCul2LA37z1SS+0=,tag:FbesWYn7mPemYbU/F8VUZg==,type:str]", - "attention": "This section contains key material that should only be modified with extra care. See `sops -h`.", + "mac": "ENC[AES256_GCM,data:PnFjXqwLfBi2R+wbe3dJTsb14e0GFiJA18bAVHDKPc1EVXpOHbtI4uswWMsCfSM23lkVLGe9nLo62V+b2KUvQrPt0AQGqCNa6oXZi0sW1rRAHFdV93x6IJ42mwHrz3MOrgbMPp32ZQYmFU0QTqAAA3zu1DW1MajbRIxECDCsOkc=,iv:QJm3YiR1NwFrSTZUMpCqLSemqwyEsg9l1ubCnMO1pP4=,tag:7qZ1+5NbP9DNefZKg1VJ8A==,type:str]", + "version": 0.8, "kms": [ { "created_at": 1444233149.795402, @@ -45,6 +45,7 @@ "enc": "-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\nhQIMA0t4uZHfl9qgARAAgQdMpnTNMCdbdFRpBsC9kxi334LbBrFUkp5lI+YzutZy\nSic85ea06FGL3O93tII9mwGAsESwKlN4nX0d31vuh/lYxMDakyd1IK/BkMG4Z1xG\n52MsACG/pyitMBXkIIyjmR0tVR+CixDsy5cUJxoWq+mfuE2ywziPY+KbEZ50hFXg\naAdKCdInXlLHdId+aXhThhXUGN1seQjtdyZjVXnp8c9hHS2YQdyp/SZf47NJ4A2y\nkO40kNS4oaHUUZIZLtzaFhWytZlpWEJJkIgH/vefL3jLW4SiIiqz24wr7MncsF+A\np8Pteulc5VrvA5CzQIq9qF3Zwn9HV2a0KWLZ/J29EYzSM8u9HLOYqsmNKt0TcVbX\n6eoG3JTJoRDrzO0DZvR3pMm4gQ0WXzHKzpu8g+JYnoQ19AMWJAPbTp5ej3MWHcXD\nXFjz4gsSYbwc4h/zVBOWsYoHlyTLUMwg2BA1YiL89xs8MIhIHOAmvM0mv+QuZQ7S\nCfc1mS04CZSmJvTcNkvE5n76n2iXs6nYNk8TYyQlhYebuQmJQKJuUYjKIHhuxZFa\n30WaSGnKHqIQn1pl7jqyqm8sVTzaKMyhbM0T+UQUJhXcWVr7r+CtRAt8XjVnJMvo\nviJwTWy1Ddo0Vu1licMFJXMnQbQlVh+CZS6FHqcbxfPaYfe7JldGmhwKg+F/NEHS\nXgEf78iLm3FNb4yeOkB/z2xjiZ3XvUAQjsUK5ofF1CJYcQ//YIFex1oO55Z0+qIt\njdDtqivLgf4SFRf0uhOxUrQNuFAvY361F1mvrGPcTubh/Ygq0aVzWzgC9gn7DTo=\n=uQw0\n-----END PGP MESSAGE-----\n" } ], - "version": 0.8 + "lastmodified": "2015-10-09T13:18:13Z", + "attention": "This section contains key material that should only be modified with extra care. See `sops -h`." } } \ No newline at end of file diff --git a/example.txt b/example.txt index 09a9de100..f74e2c7c6 100644 --- a/example.txt +++ b/example.txt @@ -1,2 +1,2 @@ -ENC[AES256_GCM,data:qe/cYirOA9x9zFw8AtonYzcRT+Sr9KEMtiRN55YOn1SNBEX7sE9s/M09KSfneKCbHIsNVdh5902vYNAwSFpJ6NhzO/6YR65ucwS1eBx4EQ7s3PYkEWHipgcibW0hXiNvEJGpR/4ZQ/er/xns2cpCUAgpv07Ry9DiGW+us4HM+gA5dplTpYUCdzMl7zGYoPYcIiJVHjkjaHK70w==,iv:v2BgZ6Oa895KpYAeikA0c9g9R8wcu2YOe2kp6vPEMX8=,tag:zQ/C7u2+veEuOVLSAEc1Mg==,type:str] -SOPS={"attention": "This section contains key material that should only be modified with extra care. See `sops -h`.", "kms": [{"arn": "arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e", "created_at": 1444233233.692422, "enc": "CiC6yCOtzsnFhkfdIslYZ0bAf//gYLYCmIu87B3sy/5yYxKnAQEBAgB4usgjrc7JxYZH3SLJWGdGwH//4GC2ApiLvOwd7Mv+cmMAAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxatks17s0ZWQIyPi8CARCAO65vxmVs4SOASbNDdnwdeOlg75rz7oeqWId2JyQU8sNyz7+TNvvsLIjIR50AGMwnbMIgTmbM99LDi6Vo"}, {"arn": "arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d", "created_at": 1444233235.129884, "enc": "CiBdfsKZbRNf/Li8Tf2SjeSdP76DineB1sbPjV0TV+meTxKnAQEBAgB4XX7CmW0TX/y4vE39ko3knT++g4p3gdbGz41dE1fpnk8AAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAzI3YJKPROE+fG2vJYCARCAO2IeX+3IeMkOOOsQauVrUTP9FVFmcmpXYDT41PDt8nhFvU/Q9RUUoVG1OLeWK+KBDZgu1NWGeUTN3TTs"}], "mac": "ENC[AES256_GCM,data:J1qg7jNkfSSFZYjgNIudoGKWKrdqmn1m26+KH6MzsDMUIcqT0LnppajHXH+HmLiV3u9KV3nvY6kFrI1M5OlmNt/iaQAHbgPiCqMYVkRqn3Us0dnGL0vIxIsA//HuGT3w3GjRVOcDIsbXpY0UHctV5ar9YuC4hIP/m4qfDwjUPwQ=,iv:e3fHDDi1PIJfqM/wvcIIhbqWJs7qo0V2I3sOgcBh3sA=,tag:jrDAl+2cRyrzB1K6BQNvow==,type:str]", "pgp": [{"created_at": "2015-10-08T15:32:06Z", "enc": "-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\nhIwDEEVDpnzXnMABA/4uvvk2EDmAkmHKu4RMTq/NGSK7ZXuY7QATPdT+M0lkQGV4\nVmHlVVXe/y2qr5ouI+k3In3Fk7HR5yFDH5G2Jz3PwuosLVw3M2XmNXZ8bvcRcvKB\nI+6WNGOC2M1bvVeqTETL77nyd5fRuhDFVjQtf/oYym6IGiX9S1UH0Mx3rkDNyNJc\nAfVY+u3DNvLI5VDXMms/XQOkwEYiCL93QnWgGbSVxDXPRp3rDXTeoWEzZNXadJ6E\nKNEnToUnVXrjOH6YwHsjDc6p6djaONxlKhy+kEdoM/+AX04ukdgvyacUfbg=\n=kYWb\n-----END PGP MESSAGE-----\n", "fp": "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"}, {"created_at": 1444233235.135862, "enc": "-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\nhQIMA0t4uZHfl9qgAQ/9GNa5B4AkO7UODicvjpsgEGLd++1mJteKOwww/08src+H\nnfe/VtTvOdCNVNwvkeKtANvM5DCX9RVTjul4SH7iKd/O9XmTFXA66fhgAbRmEczm\npzQXog/res0u/q+mVwdSDqx/6qBViIcz1Zgc5oFnAneRlAke2/UsNFuFbtaQDZZh\nuralZFdrLx/DWjqEWXEh9D+caek2z/Tjhl/PQ6JNPEa7aZfMLjuTuaoPkSgd87Zc\ndnz/UL77Wx1zdv/cLtO2XvJhOvi0BF9dkg4evouTtNJs+WjQvkBCAijwdC5JdjTz\nWj4mV4H/YdlOn+j2ng3GGmF6GIX5x9FLLD5a9PjSgHVvAH8ZpXkCVY2U8e7QAW7+\nv3KLKGZFWvke62pmypj3777Z5MBj/SJAlzmuPdCLQCXIIpozqK4N4qTvg4Rt5TsN\n8YH9HYfWhX6fHvd67alwrz4IV3g1LgCKCGQd0EXl8pjYwErspGym3UOyZKSD4dDb\nH8zdbr2bQxZ2dJR3o+DVTdohfFjxUqHAZ8bO3vkUT4xblY8n2NnIUWxw3tDHdV/6\niXWVfRcgsIRmFM8qZ7CwwxDZFgLGY3oPhzNmze+B1g5xMG/l4MbKwjCb2EQ38CDr\nDG11GMG5ewhZUDwry4aDpxQMUhvuLBupve+caHzs62zTyWxurwLwfzOHbUyCxbjS\nXAEQ++zCoKncWsAxJdaoIvAvTJBEJeRyGToPESe8iYjmkT1jYZCMj30opOmOZ94M\nE0X4OYpb8FGL/QhOASMe8eW+wYUycySePsQZaQfdIkky7olIsMTBQmSxB16D\n=lXuh\n-----END PGP MESSAGE-----\n", "fp": "85D77543B3D624B63CEA9E6DBC17301B491B3F21"}], "version": 0.8} \ No newline at end of file +ENC[AES256_GCM,data:Q0wnzAzEA+eYHxJcLu84qY6HWU6U8WD9jj5sgnx18oTvXGOJs42mLn0UUe944sB4rROV6BK6vL11YnIad5aNE9O7UC/DNsbQklB3p73olHCwCmIPErQch0Ir8gGlsQjXYb3isWgIl1jee9bFvPtNKdVojYV6clTaSGfBtAC67wC9TRT935AbzOlpdfa1G5jQiq89zHNebytGZtU=,iv:FdFKnnAlai/yZi8/O/eFNtaBWQGdETjTuVByAQ21xO0=,tag:Y1K0tobkjUPDkAXWZG3uSw==,type:str] +SOPS={"attention": "This section contains key material that should only be modified with extra care. See `sops -h`.", "kms": [{"arn": "arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e", "created_at": 1444233233.692422, "enc": "CiC6yCOtzsnFhkfdIslYZ0bAf//gYLYCmIu87B3sy/5yYxKnAQEBAgB4usgjrc7JxYZH3SLJWGdGwH//4GC2ApiLvOwd7Mv+cmMAAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxatks17s0ZWQIyPi8CARCAO65vxmVs4SOASbNDdnwdeOlg75rz7oeqWId2JyQU8sNyz7+TNvvsLIjIR50AGMwnbMIgTmbM99LDi6Vo"}, {"arn": "arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d", "created_at": 1444233235.129884, "enc": "CiBdfsKZbRNf/Li8Tf2SjeSdP76DineB1sbPjV0TV+meTxKnAQEBAgB4XX7CmW0TX/y4vE39ko3knT++g4p3gdbGz41dE1fpnk8AAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAzI3YJKPROE+fG2vJYCARCAO2IeX+3IeMkOOOsQauVrUTP9FVFmcmpXYDT41PDt8nhFvU/Q9RUUoVG1OLeWK+KBDZgu1NWGeUTN3TTs"}], "lastmodified": "2015-10-09T13:18:39Z", "mac": "ENC[AES256_GCM,data:Z2paQGLI4W6smiCB6Zfk7pec5UqPt89zBMxGNvEtcYwEivWXwAP8ueDXOzhtFEopZ1NhYX/KJrbHU4sLiI9ZjntpdGGEfzsreOXCDWLQMGnKryM1kWmc+XcsdPeq1T0i9wrY+NUy33zIYCB9UdoLKTzBEjmRPESc+Obz5ZARy4E=,iv:abqIls895sMngznd2K3kT/VsTYe/Tw0+h3HwsiT/QVA=,tag:tLUXl8MPdbe17ROY8LIphA==,type:str]", "pgp": [{"created_at": "2015-10-08T15:32:06Z", "enc": "-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\nhIwDEEVDpnzXnMABA/4uvvk2EDmAkmHKu4RMTq/NGSK7ZXuY7QATPdT+M0lkQGV4\nVmHlVVXe/y2qr5ouI+k3In3Fk7HR5yFDH5G2Jz3PwuosLVw3M2XmNXZ8bvcRcvKB\nI+6WNGOC2M1bvVeqTETL77nyd5fRuhDFVjQtf/oYym6IGiX9S1UH0Mx3rkDNyNJc\nAfVY+u3DNvLI5VDXMms/XQOkwEYiCL93QnWgGbSVxDXPRp3rDXTeoWEzZNXadJ6E\nKNEnToUnVXrjOH6YwHsjDc6p6djaONxlKhy+kEdoM/+AX04ukdgvyacUfbg=\n=kYWb\n-----END PGP MESSAGE-----\n", "fp": "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"}, {"created_at": 1444233235.135862, "enc": "-----BEGIN PGP MESSAGE-----\nVersion: GnuPG v1\n\nhQIMA0t4uZHfl9qgAQ/9GNa5B4AkO7UODicvjpsgEGLd++1mJteKOwww/08src+H\nnfe/VtTvOdCNVNwvkeKtANvM5DCX9RVTjul4SH7iKd/O9XmTFXA66fhgAbRmEczm\npzQXog/res0u/q+mVwdSDqx/6qBViIcz1Zgc5oFnAneRlAke2/UsNFuFbtaQDZZh\nuralZFdrLx/DWjqEWXEh9D+caek2z/Tjhl/PQ6JNPEa7aZfMLjuTuaoPkSgd87Zc\ndnz/UL77Wx1zdv/cLtO2XvJhOvi0BF9dkg4evouTtNJs+WjQvkBCAijwdC5JdjTz\nWj4mV4H/YdlOn+j2ng3GGmF6GIX5x9FLLD5a9PjSgHVvAH8ZpXkCVY2U8e7QAW7+\nv3KLKGZFWvke62pmypj3777Z5MBj/SJAlzmuPdCLQCXIIpozqK4N4qTvg4Rt5TsN\n8YH9HYfWhX6fHvd67alwrz4IV3g1LgCKCGQd0EXl8pjYwErspGym3UOyZKSD4dDb\nH8zdbr2bQxZ2dJR3o+DVTdohfFjxUqHAZ8bO3vkUT4xblY8n2NnIUWxw3tDHdV/6\niXWVfRcgsIRmFM8qZ7CwwxDZFgLGY3oPhzNmze+B1g5xMG/l4MbKwjCb2EQ38CDr\nDG11GMG5ewhZUDwry4aDpxQMUhvuLBupve+caHzs62zTyWxurwLwfzOHbUyCxbjS\nXAEQ++zCoKncWsAxJdaoIvAvTJBEJeRyGToPESe8iYjmkT1jYZCMj30opOmOZ94M\nE0X4OYpb8FGL/QhOASMe8eW+wYUycySePsQZaQfdIkky7olIsMTBQmSxB16D\n=lXuh\n-----END PGP MESSAGE-----\n", "fp": "85D77543B3D624B63CEA9E6DBC17301B491B3F21"}], "version": 0.8} \ No newline at end of file diff --git a/example.yaml b/example.yaml index b877b77c9..5dbb974e4 100644 --- a/example.yaml +++ b/example.yaml @@ -7,16 +7,15 @@ app2: # private key for secret operations in app2 key: |- ENC[AES256_GCM,data:78VMY0v+DvYl2LePvuDsN4SeyPQK9uBPE9L/kadbUgFF3S36OgWu4XJnDnpZfHRfsRDqlJM+mF2vze6+psRy+5o1O89FlOFpRykicV96kpToCM1TyaVzlQs0bAUWJ5S3H/pStQvU03E2Avx2KR5pxvOajPkb4orfU3nkgmnU8SJSZcLgmxC2eQgkx5ajXcQ26CLvQreczOGFtRGRo9WP3ePg93S4DcDrwjWsIqoMwS+2Pv+iAGVy+bhSleKe8WpmhtCSBpwlq9vNiykPEXktAhBugDyWgkLtTnAL3VcJ7z8xWoKIdGPBIMTgGk8Vdkuc0z6Y32bhyRvJr2xg08lZZDwyzpmP8+qSTi4gc/y4C8B8hIm6ldQMImSvdKNFs3yehxMTnensy/qT8wisX9UELaFClJZDRqgF2g7+2Oeci3c7RNa0HXt+qMjUREQ1Px4m3mi2AAvxU/bOduBmf/d0eyR/jn5I1wbDWH/IHkulfF0eAezG3PYS5BIkoN4iluPX87RBkxKjzkQmMUQCBb0pPSVjbVdTzKyhZD2gpca5rrxw3jbUU7wObfWO9EWxPdvzxxr/8Ul4rWzpohL+/2B0+SjHCOq4ZMk7wR4Y4dnZHd8gHb6U59g6ayelaYv3RCP4bHrW7dWYgfCeqKErsvGqzik=,iv:rOwVWlkdSomHVVXwBwxGLUgbsPvPBqnV7E12gcmmzlY=,tag:dliz9mVOhTA4zfBsCGVyqQ==,type:str] -number: ENC[AES256_GCM,data:uJyCZeY4/KnlJg==,iv:uTq9o812BitYNuuFPMqWAgIV6HarNErQV1JfvKb3tmU=,tag:hfNTc2iAoD40hk4lHihwTQ==,type:int] +number: ENC[AES256_GCM,data:FveYIOa4aPM4HvGm5w==,iv:7/CYCTI4aLHoYS2T3sMhibReeO29opiqzyMIXUvVD3w=,tag:3Rn+oZ+1PS7DYUlGCWJMQA==,type:float] an_array: - ENC[AES256_GCM,data:kUbSpUwaGDtAcyI=,iv:94+201+1O3Sb9SgY7kc/1QWE9H1Tk1oN42A3OshBsb8=,tag:ciZwcgXAfhhrqltDWM7ZTQ==,type:str] - ENC[AES256_GCM,data:pZWqRK5ZYpOfGHw=,iv:kSqcJz3/t78O+xDQkBDvoG6pxA1w5uzNAMlEBgnkRR8=,tag:RvniVpPKwr/o/VAvFrxqSA==,type:str] - ENC[AES256_GCM,data:oAkO6uRAV70w+ZOSScMLzUk5rtwybj0epc2tesZkeXuNuM9R0I8l34yQ2/jjCEgLcGYtqB6+i4ljGg==,iv:bniytY7Y+oZen0T3OjBBlQMoHVx4TwnYUI5IgHbf2AY=,tag:7CRdL76zQkwbumga9kWgsg==,type:str] - ENC[AES256_GCM,data:n5ZMVViz/IZwqRDgIljrQg==,iv:8A9X2UyYwyGsFKwoTO1MH69MCpUa31QJ3jSgde9i2Pc=,tag:vG4j9Y01cVg+oJ7peeA6PQ==,type:str] sops: - mac: ENC[AES256_GCM,data:AZ2oYrcDSYgvnVbKMUS35/qMfbnMz5dibgJCts1z/S6krwEXv/4+j5Mh4nZOgT+wav2WS88j8lmNzfbL81LwY7fI0ajAjNwYTQKnJvH/YP3vFyCSVuRfsR4meheg2DpdN5vALPfdmz8Ib70wgpyQLqWVgDqz46to+0RdCJHwMuk=,iv:Sy3CcFl19xxht7ZfBiwVW5RPxIeGILAt/0FgmCGPz2A=,tag:BKmcOD5XfglXh7rRlfhGfg==,type:str] - attention: This section contains key material that should only be modified with - extra care. See `sops -h`. + mac: ENC[AES256_GCM,data:uASXtE/p4eVE82+bMzctzxVZJDhjXsa+E+U9WgSEhQ43exet2edQ4ClvFl0C1oVGLbDwoeSoG3nYJ+08TrPtclEpuLpUNJaySiPwnjbCxbImw494UYVmK7WSfNcSqLmX9KEKM0VJr8cxc2A29uF2cZDNG1PB/gRoNfvWX+ax784=,iv:HMICJ1axBjGuukEc8iF8KOAMY6F+Z77aodJiMh84ZqM=,tag:9ZbE3oUermAWNMTV0LEyfg==,type:str] + version: 0.8 kms: - created_at: 1444233191.408969 enc: CiC6yCOtzsnFhkfdIslYZ0bAf//gYLYCmIu87B3sy/5yYxKnAQEBAgB4usgjrc7JxYZH3SLJWGdGwH//4GC2ApiLvOwd7Mv+cmMAAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAzV1o6Prf6blP9lLM4CARCAO+JL69F23WaIi3c2mQdHBTSUf1OdyRTq0+yFYxZCmCARmYAM3GEnTiuFMMCFP4I09TJJBBuc58/RTM0u @@ -24,7 +23,6 @@ sops: - created_at: 1444233192.474385 enc: CiBdfsKZbRNf/Li8Tf2SjeSdP76DineB1sbPjV0TV+meTxKnAQEBAgB4XX7CmW0TX/y4vE39ko3knT++g4p3gdbGz41dE1fpnk8AAAB+MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAww2lEDZcq5evsCFcACARCAOxuzZh55fs9x7WE/ZpiRKIG85bvTWVn8wFnFozK/dT3tlPmNv5JwGiXQw1BG6e+fw31npvcGoIvzkwje arn: arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d - version: 0.8 pgp: - fp: 1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A enc: | @@ -60,3 +58,6 @@ sops: FcjpqVkpIdddl1AUuY5NVBc0Xkhglz244o+xjIkULVLdlAFFGpv5CnXMLOOm5Bs= =MGKv -----END PGP MESSAGE----- + lastmodified: '2015-10-09T13:17:59Z' + attention: This section contains key material that should only be modified with + extra care. See `sops -h`. diff --git a/setup.py b/setup.py index 4bec5b2bc..4f0b8bcd8 100755 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ def read(fname): setup( name="sops", py_modules=['sops'], - version="0.8", + version="0.8.1", author="Julien Vehent", author_email="jvehent@mozilla.com", description="Secrets OPerationS (sops) is an editor of encrypted files", diff --git a/sops/__init__.py b/sops/__init__.py index 578918f0c..1618c6a87 100644 --- a/sops/__init__.py +++ b/sops/__init__.py @@ -110,6 +110,8 @@ Remove this text and add your content to the file. """ +NOW = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + def main(): argparser = argparse.ArgumentParser( @@ -193,13 +195,12 @@ def main(): # Encrypt mode: encrypt, display and exit key, tree = get_key(tree, need_key) - tree = walk_and_encrypt(tree, key, isRoot=True) + tree = walk_and_encrypt(tree, key) elif args.decrypt: # Decrypt mode: decrypt, display and exit key, tree = get_key(tree) - tree = walk_and_decrypt(tree, key, isRoot=True, - ignoreMac=args.ignore_mac) + tree = walk_and_decrypt(tree, key, ignoreMac=args.ignore_mac) else: # EDIT Mode: decrypt, edit, encrypt and save @@ -210,7 +211,7 @@ def main(): stash = dict() stash['sops'] = dict(tree['sops']) if existing_file: - tree = walk_and_decrypt(tree, key, stash=stash, isRoot=True, + tree = walk_and_decrypt(tree, key, stash=stash, ignoreMac=args.ignore_mac) # hide the sops branch during editing @@ -251,7 +252,7 @@ def main(): tree = load_file_into_tree(tmppath, otype, restore_sops=stash['sops']) os.remove(tmppath) - tree = walk_and_encrypt(tree, key, stash=stash, isRoot=True) + tree = walk_and_encrypt(tree, key, stash=stash) tree = update_sops_branch(tree, key) # if we're in -e or -d mode, and not in -i mode, display to stdout @@ -446,7 +447,7 @@ def update_sops_branch(tree, key): def walk_and_decrypt(branch, key, aad=b'', stash=None, digest=None, - isRoot=False, ignoreMac=False): + isRoot=True, ignoreMac=False): """Walk the branch recursively and decrypt leaves.""" if isRoot and not ignoreMac: digest = hashlib.sha512() @@ -461,7 +462,7 @@ def walk_and_decrypt(branch, key, aad=b'', stash=None, digest=None, nstash = stash[k] if isinstance(v, dict): branch[k] = walk_and_decrypt(v, key, aad=aad, stash=nstash, - digest=digest) + digest=digest, isRoot=False) elif isinstance(v, list): branch[k] = walk_list_and_decrypt(v, key, aad=aad, stash=nstash, digest=digest) @@ -478,8 +479,9 @@ def walk_and_decrypt(branch, key, aad=b'', stash=None, digest=None, panic("'mac' not found, unable to verify file integrity", 52) h = digest.hexdigest().upper() # We know the original hash is trustworthy because it is encrypted - # with the data key and authenticated using the tree keys - orig_h = decrypt(branch['sops']['mac'], key, aad=aad) + # with the data key and authenticated using the lastmodified timestamp + orig_h = decrypt(branch['sops']['mac'], key, + aad=branch['sops']['lastmodified'].encode('utf-8')) if h != orig_h: panic("Hash verification failed!\nexpected %s\nbut got %s" % (orig_h, h), 51) @@ -497,7 +499,7 @@ def walk_list_and_decrypt(branch, key, aad=b'', stash=None, digest=None): nstash = stash[i] if isinstance(v, dict): kl.append(walk_and_decrypt(v, key, aad=aad, stash=nstash, - digest=digest)) + digest=digest, isRoot=False)) elif isinstance(v, list): kl.append(walk_list_and_decrypt(v, key, aad=aad, stash=nstash, digest=digest)) @@ -547,7 +549,7 @@ def decrypt(value, key, aad=b'', stash=None, digest=None): def walk_and_encrypt(branch, key, aad=b'', stash=None, - isRoot=False, digest=None): + isRoot=True, digest=None): """Walk the branch recursively and encrypts its leaves.""" if isRoot: digest = hashlib.sha512() @@ -561,7 +563,7 @@ def walk_and_encrypt(branch, key, aad=b'', stash=None, if isinstance(v, dict): # recursively walk the tree branch[k] = walk_and_encrypt(v, key, aad=aad, stash=nstash, - digest=digest) + digest=digest, isRoot=False) elif isinstance(v, list): branch[k] = walk_list_and_encrypt(v, key, aad=aad, stash=nstash, digest=digest) @@ -571,9 +573,12 @@ def walk_and_encrypt(branch, key, aad=b'', stash=None, else: branch[k] = encrypt(v, key, aad=aad, stash=nstash, digest=digest) if isRoot: + branch['sops']['lastmodified'] = NOW # finalize and store the message authentication code in encrypted form h = digest.hexdigest().upper() - branch['sops']['mac'] = encrypt(h, key, aad=aad) + mac = encrypt(h, key, + aad=branch['sops']['lastmodified'].encode('utf-8')) + branch['sops']['mac'] = mac return branch @@ -586,7 +591,7 @@ def walk_list_and_encrypt(branch, key, aad=b'', stash=None, digest=None): nstash = stash[i] if isinstance(v, dict): kl.append(walk_and_encrypt(v, key, aad=aad, stash=nstash, - digest=digest)) + digest=digest, isRoot=False)) elif isinstance(v, list): kl.append(walk_list_and_encrypt(v, key, aad=aad, stash=nstash, digest=digest)) @@ -691,7 +696,7 @@ def get_key_from_kms(tree): try: kms_response = kms.decrypt(CiphertextBlob=b64decode(enc)) except Exception as e: - print("failed to decrypt key using kms: %s, skipping it" % e, + print("[warning] skipping kms %s: %s " % (entry['arn'], e), file=sys.stderr) continue return kms_response['Plaintext'] @@ -716,7 +721,7 @@ def encrypt_key_with_kms(key, entry): return entry entry['enc'] = b64encode( kms_response['CiphertextBlob']).decode('utf-8') - entry['created_at'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + entry['created_at'] = NOW return entry @@ -804,7 +809,7 @@ def encrypt_key_with_pgp(key, entry): return entry enc = enc.decode('utf-8') entry['enc'] = ruamel.yaml.scalarstring.PreservedScalarString(enc) - entry['created_at'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') + entry['created_at'] = NOW return entry diff --git a/tests/test_sops.py b/tests/test_sops.py index b3d58a15c..3daf916cc 100644 --- a/tests/test_sops.py +++ b/tests/test_sops.py @@ -140,6 +140,7 @@ class TreeTest(unittest2.TestCase): tree = OrderedDict() with mock.patch.object(builtins, 'open', m): tree = sops.load_file_into_tree('path', 'yaml') + tree['sops'] = dict() crypttree = sops.walk_and_encrypt(tree, key) assert crypttree['example_key'].startswith("ENC[AES256_GCM,data:") assert isinstance(crypttree['example_array'], list)