1package rabbitmq 2 3import ( 4 "context" 5 "fmt" 6 7 "github.com/fatih/structs" 8 "github.com/hashicorp/vault/helper/jsonutil" 9 "github.com/hashicorp/vault/logical" 10 "github.com/hashicorp/vault/logical/framework" 11) 12 13func pathListRoles(b *backend) *framework.Path { 14 return &framework.Path{ 15 Pattern: "roles/?$", 16 Callbacks: map[logical.Operation]framework.OperationFunc{ 17 logical.ListOperation: b.pathRoleList, 18 }, 19 HelpSynopsis: pathRoleHelpSyn, 20 HelpDescription: pathRoleHelpDesc, 21 } 22} 23 24func pathRoles(b *backend) *framework.Path { 25 return &framework.Path{ 26 Pattern: "roles/" + framework.GenericNameRegex("name"), 27 Fields: map[string]*framework.FieldSchema{ 28 "name": &framework.FieldSchema{ 29 Type: framework.TypeString, 30 Description: "Name of the role.", 31 }, 32 "tags": &framework.FieldSchema{ 33 Type: framework.TypeString, 34 Description: "Comma-separated list of tags for this role.", 35 }, 36 "vhosts": &framework.FieldSchema{ 37 Type: framework.TypeString, 38 Description: "A map of virtual hosts to permissions.", 39 }, 40 }, 41 Callbacks: map[logical.Operation]framework.OperationFunc{ 42 logical.ReadOperation: b.pathRoleRead, 43 logical.UpdateOperation: b.pathRoleUpdate, 44 logical.DeleteOperation: b.pathRoleDelete, 45 }, 46 HelpSynopsis: pathRoleHelpSyn, 47 HelpDescription: pathRoleHelpDesc, 48 } 49} 50 51// Reads the role configuration from the storage 52func (b *backend) Role(ctx context.Context, s logical.Storage, n string) (*roleEntry, error) { 53 entry, err := s.Get(ctx, "role/"+n) 54 if err != nil { 55 return nil, err 56 } 57 if entry == nil { 58 return nil, nil 59 } 60 61 var result roleEntry 62 if err := entry.DecodeJSON(&result); err != nil { 63 return nil, err 64 } 65 66 return &result, nil 67} 68 69// Deletes an existing role 70func (b *backend) pathRoleDelete(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 71 name := d.Get("name").(string) 72 if name == "" { 73 return logical.ErrorResponse("missing name"), nil 74 } 75 76 return nil, req.Storage.Delete(ctx, "role/"+name) 77} 78 79// Reads an existing role 80func (b *backend) pathRoleRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 81 name := d.Get("name").(string) 82 if name == "" { 83 return logical.ErrorResponse("missing name"), nil 84 } 85 86 role, err := b.Role(ctx, req.Storage, name) 87 if err != nil { 88 return nil, err 89 } 90 if role == nil { 91 return nil, nil 92 } 93 94 return &logical.Response{ 95 Data: structs.New(role).Map(), 96 }, nil 97} 98 99// Lists all the roles registered with the backend 100func (b *backend) pathRoleList(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 101 roles, err := req.Storage.List(ctx, "role/") 102 if err != nil { 103 return nil, err 104 } 105 106 return logical.ListResponse(roles), nil 107} 108 109// Registers a new role with the backend 110func (b *backend) pathRoleUpdate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { 111 name := d.Get("name").(string) 112 if name == "" { 113 return logical.ErrorResponse("missing name"), nil 114 } 115 116 tags := d.Get("tags").(string) 117 rawVHosts := d.Get("vhosts").(string) 118 119 if tags == "" && rawVHosts == "" { 120 return logical.ErrorResponse("both tags and vhosts not specified"), nil 121 } 122 123 var vhosts map[string]vhostPermission 124 if len(rawVHosts) > 0 { 125 if err := jsonutil.DecodeJSON([]byte(rawVHosts), &vhosts); err != nil { 126 return logical.ErrorResponse(fmt.Sprintf("failed to unmarshal vhosts: %s", err)), nil 127 } 128 } 129 130 // Store it 131 entry, err := logical.StorageEntryJSON("role/"+name, &roleEntry{ 132 Tags: tags, 133 VHosts: vhosts, 134 }) 135 if err != nil { 136 return nil, err 137 } 138 if err := req.Storage.Put(ctx, entry); err != nil { 139 return nil, err 140 } 141 142 return nil, nil 143} 144 145// Role that defines the capabilities of the credentials issued against it 146type roleEntry struct { 147 Tags string `json:"tags" structs:"tags" mapstructure:"tags"` 148 VHosts map[string]vhostPermission `json:"vhosts" structs:"vhosts" mapstructure:"vhosts"` 149} 150 151// Structure representing the permissions of a vhost 152type vhostPermission struct { 153 Configure string `json:"configure" structs:"configure" mapstructure:"configure"` 154 Write string `json:"write" structs:"write" mapstructure:"write"` 155 Read string `json:"read" structs:"read" mapstructure:"read"` 156} 157 158const pathRoleHelpSyn = ` 159Manage the roles that can be created with this backend. 160` 161 162const pathRoleHelpDesc = ` 163This path lets you manage the roles that can be created with this backend. 164 165The "tags" parameter customizes the tags used to create the role. 166This is a comma separated list of strings. The "vhosts" parameter customizes 167the virtual hosts that this user will be associated with. This is a JSON object 168passed as a string in the form: 169{ 170 "vhostOne": { 171 "configure": ".*", 172 "write": ".*", 173 "read": ".*" 174 }, 175 "vhostTwo": { 176 "configure": ".*", 177 "write": ".*", 178 "read": ".*" 179 } 180} 181` 182