Skip to content

Commit d5ddbb6

Browse files
authored
Merge pull request #30 from mongodb/auditing
Auditing
2 parents 71c41c8 + 4947a86 commit d5ddbb6

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

mongodbatlas/auditing.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package mongodbatlas
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
)
8+
9+
const (
10+
auditingsPath = "groups/%s/auditLog"
11+
)
12+
13+
// AuditingsService is an interface for interfacing with the Auditing
14+
// endpoints of the MongoDB Atlas API.
15+
// See more: https://docs.atlas.mongodb.com/reference/api/auditing/
16+
type AuditingsService interface {
17+
Get(context.Context, string) (*Auditing, *Response, error)
18+
Configure(context.Context, string, *Auditing) (*Auditing, *Response, error)
19+
}
20+
21+
// AuditingsServiceOp handles communication with the Auditings related methods
22+
// of the MongoDB Atlas API
23+
type AuditingsServiceOp struct {
24+
client *Client
25+
}
26+
27+
var _ AuditingsService = &AuditingsServiceOp{}
28+
29+
// Auditing represents MongoDB Maintenance Windows
30+
type Auditing struct {
31+
AuditAuthorizationSuccess *bool `json:"auditAuthorizationSuccess,omitempty"` // Indicates whether the auditing system captures successful authentication attempts for audit filters using the "atype" : "authCheck" auditing event. For more information, see auditAuthorizationSuccess
32+
AuditFilter string `json:"auditFilter,omitempty"` // JSON-formatted audit filter used by the project
33+
ConfigurationType string `json:"configurationType,omitempty"` // Denotes the configuration method for the audit filter. Possible values are: NONE - auditing not configured for the project.m FILTER_BUILDER - auditing configured via Atlas UI filter builderm FILTER_JSON - auditing configured via Atlas custom filter or API
34+
Enabled *bool `json:"enabled,omitempty"` // Denotes whether or not the project associated with the {GROUP-ID} has database auditing enabled.
35+
}
36+
37+
// Get audit configuration for the project associated with {GROUP-ID}.
38+
// See more: https://docs.atlas.mongodb.com/reference/api/auditing-get-auditLog/
39+
func (s *AuditingsServiceOp) Get(ctx context.Context, groupID string) (*Auditing, *Response, error) {
40+
if groupID == "" {
41+
return nil, nil, NewArgError("groupID", "must be set")
42+
}
43+
44+
path := fmt.Sprintf(auditingsPath, groupID)
45+
req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
46+
if err != nil {
47+
return nil, nil, err
48+
}
49+
50+
root := new(Auditing)
51+
resp, err := s.client.Do(ctx, req, root)
52+
if err != nil {
53+
return nil, resp, err
54+
}
55+
56+
return root, resp, err
57+
}
58+
59+
// Configure the audit configuration for the project associated with {GROUP-ID}.
60+
// See more: https://docs.atlas.mongodb.com/reference/api/auditing-set-auditLog/
61+
func (s *AuditingsServiceOp) Configure(ctx context.Context, groupID string, configRequest *Auditing) (*Auditing, *Response, error) {
62+
if configRequest == nil {
63+
return nil, nil, NewArgError("configRequest", "cannot be nil")
64+
}
65+
if groupID == "" {
66+
return nil, nil, NewArgError("groupID", "cannot be nil")
67+
}
68+
69+
path := fmt.Sprintf(auditingsPath, groupID)
70+
71+
req, err := s.client.NewRequest(ctx, http.MethodPatch, path, configRequest)
72+
if err != nil {
73+
return nil, nil, err
74+
}
75+
76+
root := new(Auditing)
77+
resp, err := s.client.Do(ctx, req, root)
78+
if err != nil {
79+
return nil, resp, err
80+
}
81+
82+
return root, resp, err
83+
}

mongodbatlas/auditing_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package mongodbatlas
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"testing"
8+
9+
"github.com/go-test/deep"
10+
"github.com/mwielbut/pointy"
11+
)
12+
13+
func TestConfigureAuditing(t *testing.T) {
14+
setup()
15+
defer teardown()
16+
17+
groupID := "6d2065c687d9d64ae7acdg41"
18+
19+
mux.HandleFunc(fmt.Sprintf("/"+auditingsPath, groupID), func(w http.ResponseWriter, r *http.Request) {
20+
expected := map[string]interface{}{
21+
"auditAuthorizationSuccess": false,
22+
"auditFilter": "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
23+
"enabled": true,
24+
}
25+
26+
var v map[string]interface{}
27+
err := json.NewDecoder(r.Body).Decode(&v)
28+
if err != nil {
29+
t.Fatalf("decode json: %v", err)
30+
}
31+
32+
if diff := deep.Equal(v, expected); diff != nil {
33+
t.Errorf("Request body\n got=%#v\nwant=%#v \n\ndiff=%#v", v, expected, diff)
34+
}
35+
36+
fmt.Fprint(w, `{
37+
"auditAuthorizationSuccess": false,
38+
"auditFilter": "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
39+
"configurationType": "FILTER_JSON",
40+
"enabled": true
41+
}`)
42+
})
43+
44+
auditingRequest := &Auditing{
45+
AuditAuthorizationSuccess: pointy.Bool(false),
46+
AuditFilter: "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
47+
Enabled: pointy.Bool(true),
48+
}
49+
50+
auditingResponse, _, err := client.Auditing.Configure(ctx, groupID, auditingRequest)
51+
if err != nil {
52+
t.Errorf("Auditing.Configure returned error: %v", err)
53+
return
54+
}
55+
56+
expected := &Auditing{
57+
AuditAuthorizationSuccess: pointy.Bool(false),
58+
AuditFilter: "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
59+
ConfigurationType: "FILTER_JSON",
60+
Enabled: pointy.Bool(true),
61+
}
62+
63+
if diff := deep.Equal(auditingResponse, expected); diff != nil {
64+
t.Errorf("Request body\n got=%#v\nwant=%#v \n\ndiff=%#v", auditingResponse, expected, diff)
65+
}
66+
}
67+
68+
func TestAuditing_Get(t *testing.T) {
69+
setup()
70+
defer teardown()
71+
72+
groupID := "6d2065c687d9d64ae7acdg41"
73+
74+
mux.HandleFunc(fmt.Sprintf("/"+auditingsPath, groupID), func(w http.ResponseWriter, r *http.Request) {
75+
testMethod(t, r, http.MethodGet)
76+
fmt.Fprint(w, fmt.Sprintf(`{
77+
"auditAuthorizationSuccess": false,
78+
"auditFilter": "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
79+
"configurationType": "FILTER_JSON",
80+
"enabled": true
81+
}`))
82+
})
83+
84+
auditing, _, err := client.Auditing.Get(ctx, groupID)
85+
if err != nil {
86+
t.Errorf("Auditing.Get returned error: %v", err)
87+
}
88+
89+
expected := &Auditing{
90+
AuditAuthorizationSuccess: pointy.Bool(false),
91+
AuditFilter: "{\n \"atype\": \"authenticate\",\n \"param\": {\n \"user\": \"auditAdmin\",\n \"db\": \"admin\",\n \"mechanism\": \"SCRAM-SHA-1\"\n }\n}",
92+
ConfigurationType: "FILTER_JSON",
93+
Enabled: pointy.Bool(true),
94+
}
95+
96+
if diff := deep.Equal(auditing, expected); diff != nil {
97+
t.Errorf("Request body\n got=%#v\nwant=%#v \n\ndiff=%#v", auditing, expected, diff)
98+
}
99+
}

mongodbatlas/mongodbatlas.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type Client struct {
4949
Teams TeamsService
5050
AtlasUsers AtlasUsersService
5151
GlobalClusters GlobalClustersService
52+
Auditing AuditingsService
5253

5354
onRequestCompleted RequestCompletionCallback
5455
}
@@ -157,6 +158,7 @@ func NewClient(httpClient *http.Client) *Client {
157158
c.Teams = &TeamsServiceOp{client: c}
158159
c.AtlasUsers = &AtlasUsersServiceOp{client: c}
159160
c.GlobalClusters = &GlobalClustersServiceOp{client: c}
161+
c.Auditing = &AuditingsServiceOp{client: c}
160162

161163
return c
162164
}

0 commit comments

Comments
 (0)