1package api
2
3import (
4	"context"
5	"errors"
6	"fmt"
7
8	"github.com/mitchellh/mapstructure"
9)
10
11func (c *Sys) AuditHash(path string, input string) (string, error) {
12	body := map[string]interface{}{
13		"input": input,
14	}
15
16	r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit-hash/%s", path))
17	if err := r.SetJSONBody(body); err != nil {
18		return "", err
19	}
20
21	ctx, cancelFunc := context.WithCancel(context.Background())
22	defer cancelFunc()
23	resp, err := c.c.RawRequestWithContext(ctx, r)
24	if err != nil {
25		return "", err
26	}
27	defer resp.Body.Close()
28
29	secret, err := ParseSecret(resp.Body)
30	if err != nil {
31		return "", err
32	}
33	if secret == nil || secret.Data == nil {
34		return "", errors.New("data from server response is empty")
35	}
36
37	hash, ok := secret.Data["hash"]
38	if !ok {
39		return "", errors.New("hash not found in response data")
40	}
41	hashStr, ok := hash.(string)
42	if !ok {
43		return "", errors.New("could not parse hash in response data")
44	}
45
46	return hashStr, nil
47}
48
49func (c *Sys) ListAudit() (map[string]*Audit, error) {
50	r := c.c.NewRequest("GET", "/v1/sys/audit")
51
52	ctx, cancelFunc := context.WithCancel(context.Background())
53	defer cancelFunc()
54	resp, err := c.c.RawRequestWithContext(ctx, r)
55
56	if err != nil {
57		return nil, err
58	}
59	defer resp.Body.Close()
60
61	secret, err := ParseSecret(resp.Body)
62	if err != nil {
63		return nil, err
64	}
65	if secret == nil || secret.Data == nil {
66		return nil, errors.New("data from server response is empty")
67	}
68
69	mounts := map[string]*Audit{}
70	err = mapstructure.Decode(secret.Data, &mounts)
71	if err != nil {
72		return nil, err
73	}
74
75	return mounts, nil
76}
77
78// DEPRECATED: Use EnableAuditWithOptions instead
79func (c *Sys) EnableAudit(
80	path string, auditType string, desc string, opts map[string]string) error {
81	return c.EnableAuditWithOptions(path, &EnableAuditOptions{
82		Type:        auditType,
83		Description: desc,
84		Options:     opts,
85	})
86}
87
88func (c *Sys) EnableAuditWithOptions(path string, options *EnableAuditOptions) error {
89	r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit/%s", path))
90	if err := r.SetJSONBody(options); err != nil {
91		return err
92	}
93
94	ctx, cancelFunc := context.WithCancel(context.Background())
95	defer cancelFunc()
96	resp, err := c.c.RawRequestWithContext(ctx, r)
97
98	if err != nil {
99		return err
100	}
101	defer resp.Body.Close()
102
103	return nil
104}
105
106func (c *Sys) DisableAudit(path string) error {
107	r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/audit/%s", path))
108
109	ctx, cancelFunc := context.WithCancel(context.Background())
110	defer cancelFunc()
111	resp, err := c.c.RawRequestWithContext(ctx, r)
112
113	if err == nil {
114		defer resp.Body.Close()
115	}
116	return err
117}
118
119// Structures for the requests/resposne are all down here. They aren't
120// individually documented because the map almost directly to the raw HTTP API
121// documentation. Please refer to that documentation for more details.
122
123type EnableAuditOptions struct {
124	Type        string            `json:"type" mapstructure:"type"`
125	Description string            `json:"description" mapstructure:"description"`
126	Options     map[string]string `json:"options" mapstructure:"options"`
127	Local       bool              `json:"local" mapstructure:"local"`
128}
129
130type Audit struct {
131	Type        string            `json:"type" mapstructure:"type"`
132	Description string            `json:"description" mapstructure:"description"`
133	Options     map[string]string `json:"options" mapstructure:"options"`
134	Local       bool              `json:"local" mapstructure:"local"`
135	Path        string            `json:"path" mapstructure:"path"`
136}
137