/vendor/github.com/hashicorp/vault/builtin/logical/rabbitmq/path_role_create.go

https://github.com/Caiyeon/goldfish · Go · 120 lines · 93 code · 17 blank · 10 comment · 25 complexity · b0ec4ba3643f94c3ed1c33330bea5af7 MD5 · raw file

  1. package rabbitmq
  2. import (
  3. "fmt"
  4. "github.com/hashicorp/go-uuid"
  5. "github.com/hashicorp/vault/logical"
  6. "github.com/hashicorp/vault/logical/framework"
  7. "github.com/michaelklishin/rabbit-hole"
  8. )
  9. func pathCreds(b *backend) *framework.Path {
  10. return &framework.Path{
  11. Pattern: "creds/" + framework.GenericNameRegex("name"),
  12. Fields: map[string]*framework.FieldSchema{
  13. "name": &framework.FieldSchema{
  14. Type: framework.TypeString,
  15. Description: "Name of the role.",
  16. },
  17. },
  18. Callbacks: map[logical.Operation]framework.OperationFunc{
  19. logical.ReadOperation: b.pathCredsRead,
  20. },
  21. HelpSynopsis: pathRoleCreateReadHelpSyn,
  22. HelpDescription: pathRoleCreateReadHelpDesc,
  23. }
  24. }
  25. // Issues the credential based on the role name
  26. func (b *backend) pathCredsRead(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
  27. name := d.Get("name").(string)
  28. if name == "" {
  29. return logical.ErrorResponse("missing name"), nil
  30. }
  31. // Get the role
  32. role, err := b.Role(req.Storage, name)
  33. if err != nil {
  34. return nil, err
  35. }
  36. if role == nil {
  37. return logical.ErrorResponse(fmt.Sprintf("unknown role: %s", name)), nil
  38. }
  39. // Ensure username is unique
  40. uuidVal, err := uuid.GenerateUUID()
  41. if err != nil {
  42. return nil, err
  43. }
  44. username := fmt.Sprintf("%s-%s", req.DisplayName, uuidVal)
  45. password, err := uuid.GenerateUUID()
  46. if err != nil {
  47. return nil, err
  48. }
  49. // Get the client configuration
  50. client, err := b.Client(req.Storage)
  51. if err != nil {
  52. return nil, err
  53. }
  54. if client == nil {
  55. return logical.ErrorResponse("failed to get the client"), nil
  56. }
  57. // Register the generated credentials in the backend, with the RabbitMQ server
  58. if _, err = client.PutUser(username, rabbithole.UserSettings{
  59. Password: password,
  60. Tags: role.Tags,
  61. }); err != nil {
  62. return nil, fmt.Errorf("failed to create a new user with the generated credentials")
  63. }
  64. // If the role had vhost permissions specified, assign those permissions
  65. // to the created username for respective vhosts.
  66. for vhost, permission := range role.VHosts {
  67. if _, err := client.UpdatePermissionsIn(vhost, username, rabbithole.Permissions{
  68. Configure: permission.Configure,
  69. Write: permission.Write,
  70. Read: permission.Read,
  71. }); err != nil {
  72. // Delete the user because it's in an unknown state
  73. if _, rmErr := client.DeleteUser(username); rmErr != nil {
  74. return nil, fmt.Errorf("failed to delete user:%s, err: %s. %s", username, err, rmErr)
  75. }
  76. return nil, fmt.Errorf("failed to update permissions to the %s user. err:%s", username, err)
  77. }
  78. }
  79. // Return the secret
  80. resp := b.Secret(SecretCredsType).Response(map[string]interface{}{
  81. "username": username,
  82. "password": password,
  83. }, map[string]interface{}{
  84. "username": username,
  85. })
  86. // Determine if we have a lease
  87. lease, err := b.Lease(req.Storage)
  88. if err != nil {
  89. return nil, err
  90. }
  91. if lease != nil {
  92. resp.Secret.TTL = lease.TTL
  93. }
  94. return resp, nil
  95. }
  96. const pathRoleCreateReadHelpSyn = `
  97. Request RabbitMQ credentials for a certain role.
  98. `
  99. const pathRoleCreateReadHelpDesc = `
  100. This path reads RabbitMQ credentials for a certain role. The
  101. RabbitMQ credentials will be generated on demand and will be automatically
  102. revoked when the lease is up.
  103. `