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

cmd: Add client secret encryption option #1322

Merged
merged 4 commits into from
Mar 29, 2019
Merged

Conversation

sawadashota
Copy link
Contributor

@sawadashota sawadashota commented Mar 20, 2019

Related issue

#1317

Proposed changes

Add client secret encryption option.

It behaves following

  • hydra clients create --pgp-key=<base64 encoded PGP encryption key> ...
  • hydra clients create --pgp-key-url=<PGP encryption key URL> ...
  • hydra clients create --keybase=<Keybase username> ...

Then stdout will be like following

OAuth 2.0 Client ID: 15af00e5-6485-4f4b-bca7-713fc4868ff0
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAwPgHOeBl4vs70ejaYXPKYWYEwxkCx8i8tBbRFjonsENg42Mul+U1M/hfA2IU7xxXdurYvAxWH02u80oVvLV0EmAhzK8a7/YiafC5c1VhSWYmZ62vQEeSN/G0kxkCwepamg216+9GkGNiD17Tacd2KKlnlibnOXTfF9Vzzf5RpHKX0Z/154mdMyagy//q77wpJkoKEzqLqiL3+p7HOJqdRqvOs7xbagHraN1D6G+oa/M3S+bBbny+YxdHcXsV7ihWuARREuEKMdylMkFeCf3ZSdUoF9GgYrfARRmoplQsvOhwyH4dyJT7ux8z+fEAjNpz1Lmmxj8E4rDtNNfcdR5/G+BGV6eOR+rwecXVtNDFobFSLWd3zK5FBJlRebNag3NBstvHu8PzVR50suVFiX8YRUaabRY/pRupB0VQ7O0R79tkWuV4RtSHvwQHu3dVineaqDtNTPgbkrj9z2zrOqmPk2scb7ClqRCdtGarHsQFHxAWs1J2m+Tyj1syOIwTYhgUKB3RFuOdQ215cXNHGpsY8eaW21is1Ta3zjc7HbYtwTiKRibq8Wl/hV5SInOgYbC98xpHkpKBDeeyln335zzOQRbXHpccKe5mroVLyZSY5azkZ4uf18g18VkxP2bs703MkMTLIZLg7wo8JlIjAQOLMaIyEpB77X/bC8rsnoSw1NHS4AHk636Fh7D18F+aeYbNubLZseF30+C34DrhG4ngFOJ3t+J84Cfkqz4ryIPAiZ84mY0Sv3R4UOC049iDVpNERLq94NzhMJvgGuQSeIeAytDDXkbylonSV1yB4uXyiGThXFAA

To decrypt this, private key holder executes base64 decode and PGP decrypt.
Following is an example for keybase.

$ echo ${client_secret} | base64 --decode | keybase pgp decrypt
# raw password here

When an error occurred, client create request will be canceled and stdout will be like following

Failed to load encryption key: openpgp: invalid argument: no armored data found
exit status 1
Full Example

Create Client With Client Secret Encryption

$ go run main.go clients create --name 'example13' --grant-types 'client_credentials' --response-types 'token' --scope 'hoge' --pgp-key "${base64_encoded_pgp_key}" --endpoint 'http://localhost:4445'
OAuth 2.0 Client ID: 5dcb90fe-a216-47fa-a115-04aaa56fd13d
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAZu8fdlmrCYidbMTYFXY0x4Qh7MEJBWmAZ2lWczx/6DZEugGQ+p3o0QbhcXzgS5AXUkSCyR1qTp1rjW+X18NNHx+prh7BrtVdj6CW+WqmH3IGCXdUZF0qE0tCxOJt752qsD6d7bVe8NsvEu891syfYStqi760MW/KHQxqhp7TQX7QAo6GfqX9b2ScpmIyZ/wD3aapPHBxhtEDzq6T0Hmz1RpGh7RW99nqaPQcLUWOJzans51Sk8RHtZdMAHlgusShxwGk92Z1L8g+D3SvoIu58JATVy7uRzeILjowVY8pc8Qhlr75lzcXQL6zcB2LIlbS15j0ICFweTfrFMhLNrermCDZMfWrGxHy2r7n1TwRRWOii8h2Sv0cBRPW/TH6dHBlwRzkEGo9X4/2ZCMKvbQ+FPi7AKzKptPe0/SrQwwbLItOWkiL5ySr+RTRd8r4iQIE3ZUhrpX918uLfr/ZYksveNCGeYRYf77b+CS0L0BWoWCBZOiGbReu9+RHdt9rrfJvHTUJbQ6AJYNwZh6CKFr1Wb2OxCsaUd597e0xrtzx9nLiZdG7gZbQriWwL+jyA9bE2c5v7v0qINtKbeK7IlLFdunvLSH5Vny9B7qc1j5A6mJ4ZAQCaeMZGSGE0kIMwrIAt21tp98xgd/6yL/KXjFx2U6j5fJnQHn9V1b5EzHN6ObS4AHkckUDGzf+MCo+KXnlsQfm/+G71uDK4B3hqZTgXeKJtDXe4OPkTmMw9DWXp3QcE396Sz9LceAx43lctYUszisn4Gvh7/HgBuR+xFSnBxzyOw2g0uE+ySFg4tPdVIHhXqcA

$ go run main.go clients create --name 'example14' --grant-types 'client_credentials' --response-types 'token' --scope 'hoge' --pgp-key-url 'https://keybase.io/sawadashota/pgp_keys.asc' --endpoint 'http://localhost:4445'
OAuth 2.0 Client ID: 8dc53b81-afed-44b2-8509-87ef7e83a376
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAwPgHOeBl4vs70ejaYXPKYWYEwxkCx8i8tBbRFjonsENg42Mul+U1M/hfA2IU7xxXdurYvAxWH02u80oVvLV0EmAhzK8a7/YiafC5c1VhSWYmZ62vQEeSN/G0kxkCwepamg216+9GkGNiD17Tacd2KKlnlibnOXTfF9Vzzf5RpHKX0Z/154mdMyagy//q77wpJkoKEzqLqiL3+p7HOJqdRqvOs7xbagHraN1D6G+oa/M3S+bBbny+YxdHcXsV7ihWuARREuEKMdylMkFeCf3ZSdUoF9GgYrfARRmoplQsvOhwyH4dyJT7ux8z+fEAjNpz1Lmmxj8E4rDtNNfcdR5/G+BGV6eOR+rwecXVtNDFobFSLWd3zK5FBJlRebNag3NBstvHu8PzVR50suVFiX8YRUaabRY/pRupB0VQ7O0R79tkWuV4RtSHvwQHu3dVineaqDtNTPgbkrj9z2zrOqmPk2scb7ClqRCdtGarHsQFHxAWs1J2m+Tyj1syOIwTYhgUKB3RFuOdQ215cXNHGpsY8eaW21is1Ta3zjc7HbYtwTiKRibq8Wl/hV5SInOgYbC98xpHkpKBDeeyln335zzOQRbXHpccKe5mroVLyZSY5azkZ4uf18g18VkxP2bs703MkMTLIZLg7wo8JlIjAQOLMaIyEpB77X/bC8rsnoSw1NHS4AHk636Fh7D18F+aeYbNubLZseF30+C34DrhG4ngFOJ3t+J84Cfkqz4ryIPAiZ84mY0Sv3R4UOC049iDVpNERLq94NzhMJvgGuQSeIeAytDDXkbylonSV1yB4uXyiGThXFAA

$ go run main.go clients create --name 'example15' --grant-types 'client_credentials' --response-types 'token' --scope 'hoge' --keybase 'sawadashota' --endpoint 'http://localhost:4445'
OAuth 2.0 Client ID: 35bf1a2c-2c59-4f1c-b4d9-0e0c40bc2d32
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAHty6X3fvHWPFVl4b8puEkejLhWlt9mge9iv0LYqHiKefITRCbyBxjzIxRUIJatjno8tg/twx9tisRZf/GwtitaxekS3+j5QZa5Sosg4CAGUPpOwZw1NKM9gr5129+hVW8OHmWr+ieJBUF3B1PYNgximSQ7oyLYOv5M4D1Oy8yINA0DIVzMBlQ6Akg1H3wRkIVKQmo83FRAzSJW0Bg0yXpmI83MqI0NnE4Qvqw5rJSXUZ/GMRF+QIaK1QIniNgfqARWlQq4neBUG90men/qfahE+j0F7/ELraaw52BcY1cYpFkUY8MBYyCurYEP1hb9KQOUvQbFcyHoBO4bge8CuC+I+Dlvc0WAnHNCczfP0F9NW5os+2ADPBE8yM9SqMo50KtDlH1sL6KOtFUtCoTvFkECA9DD/QtiPfLmr2T5X8up+MUFPYQyq5NS5RxZdNUVIUGy+c/LcmDUNTd8UTKk8hv7cHPWHMch82FDOF5+js58W56kmwJS0Tt2Hu9P7jja2zvi44Osl5mgf4F2qFYKGMUKxcKfoKCNwRvfr3IITJ544LLqkQi70LbNQ4ckSnYHQlTu1/bkpgOnHDxouIgRQMhgnBavKBTyn8059mpUmTjTUzlLB640q/s9ckWExl0QgTbFIYKB8d4Iw/gNTwLl8Zu++KH3yUQxkNREi0JUaGnBjS4AHkKPQfXe4Uklt3XxjX2GM6vOGYLuAl4DLhVxHguOKVetmp4H/k7g4lOwyWXrH+lxErJnUyjuC04+P3uAVb0QtM4C7hslTgEeSTHjRjNSX5/LcdSi6Bj+/b4hlQqbvhNzoA

Import Client

$ go run main.go clients import /path/to/client.json /path/to/client.json --keybase sawadashota
Imported OAuth 2.0 Client b57b7516-879d-4668-8cca-12746a11f6e7 from: /path/to/client.json
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAXywK20GzQyQaFGwEroU7LO5eHi4CWG8JhXOiBAhuXgpNY4Avx3Xc9YLZjk6IwEzab0p/kwTBmMSEYsi512+CT9zYp0t4Bk0TLCj59++tzixTMQ98vu9gYsnsQHGLl6YG0rUpnrBxsOmrhSqg8keD9qAJt79OAppUe3iKN/dpiF+VatEQeuafCmdoO2AhpEPsm6vRBIzYaivLj/dxcNXEp8A15exBx1CCyomieVL9g3WQMrZbctONTmu48Rw8eEvmU9xAzZCkJ9h59C2xZp8g209k8xyz8CZmjhRI4DqqyFKa6zqy2GAL+SvZ0PNRa4TB4nmMdxw0DqeLibxgNfArVJOUFZaW+qDiwDYVExz7nYw1z41XLSqprDPvwA2DeJQmndB1qPM7oH1C1SQ8AESPR0WxuuSWNOdLHggLKnng/JimiBT66YNvkGKuZt//g5Id2/l5MpmAxg4lKBz+nEBEIJiyro5xWRNMOgX0OHtfho7waTzjYUtAlnSwuKE5eyHGu0v0WsPdc/jH2baNunmW0K0LDXyzq5Cwz9IqGAb4Obl1qOGUrVu1343f1uyZ9ksKfnCmeK2ur9+sifighDa1rEupgXHFXA0Kwa3CbM82AoBLE6jqTqBZKD09qv3rFIOjH9d3SofYiP+7pYm8I07xqiTNQMBQnM4rD/g3e++TDVrS4AHkPYisTQ0Mn+n4WalXFtArkOG75eA54O/hZ03g1OLFeC3m4O7jTLW2+qLHihTgbOI/wE6c

Imported OAuth 2.0 Client 5b256faf-0697-4eaa-8cd1-a0cde7088d3b from: /path/to/client.json
OAuth 2.0 Encrypted Client Secret: wcFMA7nE0EzOyuXVARAAEkHPoGGuTa0mst4xfQfpIm4H0MZU1z5yir4349cSF3eVhL6m1FzDFcfZ7XfV8ON0QXMlA7KOTbLLY6FGJQWsCWL68hzWrij9fiSgt/AKwuAV0IuZy4Wsz6zMcjxVX+HvCSQF5s5RyF5H/Ki/PGYAdSlInzLuG/Ylhqrdvcw8gLN7N01sNENkSdGojOw+D/rnMcqksbKpkYZkbbKH2LulEIaAlVqMAXYnVoz0yHaUhvgY98EUWonhoxNATTXyshXnPdY5nJoBpymCV2EqYPN5GrXzpaRleAuHDdM7n3rQ/jvR9Dz6Njcj8+32CW8uw15J+LXsWr9ys3Ebs8G+pkq57JfCyWW1uW3BvxpgMQGt+64e6+dj/QC9g7C5sevRtZRv04UGmnKB6MnrhpDRneq7bfIZlfc6MaAJRkTGu1SqztMzEGjEQSHEhq4m+3tXk8y3G0npdM62uXb3N6MjX9vllbvKb6HH/a2JdQKxCy6gS8+eqWLo11+150IBSPovhFOmKWUP2rS11NJFMw5PGvewW5YuJ1PH/Uw3w+q5mF0Y55ID6Tohpb0lAeIE6TiWJyVC9HHYPZ5LeXAZ14UfsxHEokHFad+93YGuMb+2rcZ0FOb9HR57cs9Osi0aqP6aVZA0xwW//qAY2Cf9yZEHEKqgXgFHzvGekVic5qPGZ7+FT3jS4AHkdQek75WiMaGGV+CH8KBn6uGbaeAF4PfhL0LgT+LMIhDI4EPjhWyzQ811+Z3gYuJqmv5X

Decrypt Client Secret

# decrypt by keybase command
$ echo 'wcFMA7nE0EzOyuXVARAAZu8fdlmrCYidbMTYFXY0x4Qh7MEJBWmAZ2lWczx/6DZEugGQ+p3o0QbhcXzgS5AXUkSCyR1qTp1rjW+X18NNHx+prh7BrtVdj6CW+WqmH3IGCXdUZF0qE0tCxOJt752qsD6d7bVe8NsvEu891syfYStqi760MW/KHQxqhp7TQX7QAo6GfqX9b2ScpmIyZ/wD3aapPHBxhtEDzq6T0Hmz1RpGh7RW99nqaPQcLUWOJzans51Sk8RHtZdMAHlgusShxwGk92Z1L8g+D3SvoIu58JATVy7uRzeILjowVY8pc8Qhlr75lzcXQL6zcB2LIlbS15j0ICFweTfrFMhLNrermCDZMfWrGxHy2r7n1TwRRWOii8h2Sv0cBRPW/TH6dHBlwRzkEGo9X4/2ZCMKvbQ+FPi7AKzKptPe0/SrQwwbLItOWkiL5ySr+RTRd8r4iQIE3ZUhrpX918uLfr/ZYksveNCGeYRYf77b+CS0L0BWoWCBZOiGbReu9+RHdt9rrfJvHTUJbQ6AJYNwZh6CKFr1Wb2OxCsaUd597e0xrtzx9nLiZdG7gZbQriWwL+jyA9bE2c5v7v0qINtKbeK7IlLFdunvLSH5Vny9B7qc1j5A6mJ4ZAQCaeMZGSGE0kIMwrIAt21tp98xgd/6yL/KXjFx2U6j5fJnQHn9V1b5EzHN6ObS4AHkckUDGzf+MCo+KXnlsQfm/+G71uDK4B3hqZTgXeKJtDXe4OPkTmMw9DWXp3QcE396Sz9LceAx43lctYUszisn4Gvh7/HgBuR+xFSnBxzyOw2g0uE+ySFg4tPdVIHhXqcA' | base64 --decode | keybase pgp decrypt
1O9pdfgUNu_PWA7jk7HbdjJE2L

# decrypt by gpg command (equivalent above) 
$ gpg --decrypt <(echo 'wcFMA7nE0EzOyuXVARAAZu8fdlmrCYidbMTYFXY0x4Qh7MEJBWmAZ2lWczx/6DZEugGQ+p3o0QbhcXzgS5AXUkSCyR1qTp1rjW+X18NNHx+prh7BrtVdj6CW+WqmH3IGCXdUZF0qE0tCxOJt752qsD6d7bVe8NsvEu891syfYStqi760MW/KHQxqhp7TQX7QAo6GfqX9b2ScpmIyZ/wD3aapPHBxhtEDzq6T0Hmz1RpGh7RW99nqaPQcLUWOJzans51Sk8RHtZdMAHlgusShxwGk92Z1L8g+D3SvoIu58JATVy7uRzeILjowVY8pc8Qhlr75lzcXQL6zcB2LIlbS15j0ICFweTfrFMhLNrermCDZMfWrGxHy2r7n1TwRRWOii8h2Sv0cBRPW/TH6dHBlwRzkEGo9X4/2ZCMKvbQ+FPi7AKzKptPe0/SrQwwbLItOWkiL5ySr+RTRd8r4iQIE3ZUhrpX918uLfr/ZYksveNCGeYRYf77b+CS0L0BWoWCBZOiGbReu9+RHdt9rrfJvHTUJbQ6AJYNwZh6CKFr1Wb2OxCsaUd597e0xrtzx9nLiZdG7gZbQriWwL+jyA9bE2c5v7v0qINtKbeK7IlLFdunvLSH5Vny9B7qc1j5A6mJ4ZAQCaeMZGSGE0kIMwrIAt21tp98xgd/6yL/KXjFx2U6j5fJnQHn9V1b5EzHN6ObS4AHkckUDGzf+MCo+KXnlsQfm/+G71uDK4B3hqZTgXeKJtDXe4OPkTmMw9DWXp3QcE396Sz9LceAx43lctYUszisn4Gvh7/HgBuR+xFSnBxzyOw2g0uE+ySFg4tPdVIHhXqcA' | base64 --decode)
gpg: encrypted with 4096-bit RSA key, ID xxxxxxxxxxx, created xxxx-xx-xx
      "XXXX XXXXX <xxxxx@example.com>"
1O9pdfgUNu_PWA7jk7HbdjJE2L

Error Pattern

$ go run main.go clients create --name 'example14' --grant-types 'client_credentials' --response-types 'token' --scope 'hoge' --pgp-key-url 'http://example.com/' --endpoint 'http://localhost:4445'
Failed to load encryption key: openpgp: invalid argument: no armored data found
exit status 1

Checklist

  • I have read the contributing guidelines
  • I confirm that this pull request does not address a security vulnerability. If this pull request addresses a security
    vulnerability, I confirm that I got green light (please contact hi@ory.sh) from the maintainers to push the changes.
  • I signed the Developer's Certificate of Origin
    by signing my commit(s). You can amend your signature to the most recent commit by using git commit --amend -s. If you
    amend the commit, you might need to force push using git push --force HEAD:<branch>. Please be very careful when using
    force push.
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation within the code base (if appropriate)
  • I have documented my changes in the developer guide (if appropriate)

Further comments

I put implementation for encryption my repository because I'm not sure where to put.
Let's talk about it. And when it will be clear where to put it, I can re-implement hydra or ory's library.
https://github.com/sawadashota/encrypta

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty good! It would be great if you could add an example to the help command, somewhere around here.

Also, it would probably make sense to have this feature in clients import as well. Maybe move this stuff to a helper function (which would also allow testing this functionality) and use it for both import and create!

cmd/cli/handler_client.go Outdated Show resolved Hide resolved
@sawadashota
Copy link
Contributor Author

Thanks for reviewing!
I also applied import and added example.
And I'm sorry but it is hard to write test for helper because it seems to be test for function but library :(

@@ -56,6 +56,11 @@ func (h *ClientHandler) ImportClients(cmd *cobra.Command, args []string) {
cmdx.MinArgs(cmd, args, 1)
m := h.newClientManager(cmd)

ek, encryptSecret, err := newEncryptionKey(cmd, nil)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmdx.Must will automatically skip if err == nil, so you can leave out the if check!

@@ -92,6 +109,11 @@ func (h *ClientHandler) CreateClient(cmd *cobra.Command, args []string) {
fmt.Println("You should not provide secrets using command line flags, the secret might leak to bash history and similar systems")
}

ek, encryptSecret, err := newEncryptionKey(cmd, nil)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aeneasr
Copy link
Member

aeneasr commented Mar 25, 2019

And I'm sorry but it is hard to write test for helper because it seems to be test for function but library :(

You could add a test with cmd line flags here: https://github.com/ory/hydra/blob/master/cmd/root_test.go#L116

@aeneasr aeneasr added this to the v1.0.0 milestone Mar 26, 2019
Signed-off-by: Shota Sawada <xiootas@gmail.com>
Signed-off-by: Shota Sawada <xiootas@gmail.com>
Signed-off-by: Shota Sawada <xiootas@gmail.com>
Signed-off-by: Shota Sawada <xiootas@gmail.com>
@sawadashota
Copy link
Contributor Author

Thanks! I added test PGP keys and test case :)

@aeneasr
Copy link
Member

aeneasr commented Mar 29, 2019

Awesome! Thanks :)

@aeneasr aeneasr merged commit 468076e into ory:master Mar 29, 2019
@sawadashota sawadashota deleted the fix-1317 branch March 30, 2019 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants