Enhance audit logging with extra data (#70)
<!--- Provide a general summary of your changes in the Title above --> ## Description Enhance audit logging by including request details and IP addresses in audit entries ## Motivation and Context <!--- Why is this change required? What problem does it solve? --> <!--- If it fixes an open issue, please link to the issue here. --> ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [ ] My change requires a change to the documentation or CHANGELOG. - [ ] I have updated the documentation/CHANGELOG accordingly. - [ ] I have created a feature (non-master) branch for my PR.
This commit is contained in:
commit
6f468da9e7
|
|
@ -827,14 +827,14 @@ func (p *OAuthProxy) backendLogout(rw http.ResponseWriter, req *http.Request, si
|
||||||
if resp.StatusCode() != 200 {
|
if resp.StatusCode() != 200 {
|
||||||
logger.Errorf("error while calling backend logout url, returned error code %v", resp.StatusCode())
|
logger.Errorf("error while calling backend logout url, returned error code %v", resp.StatusCode())
|
||||||
}
|
}
|
||||||
p.picsAuditClient.CreateSuccessfulLogoutAuditEntry(session, req.RequestURI, req.Header.Get("edisp-org-id"))
|
p.picsAuditClient.CreateSuccessfulLogoutAuditEntry(session, req.RequestURI, req.Header.Get("edisp-org-id"), req)
|
||||||
} else {
|
} else {
|
||||||
if providerData.BackendRevokeAccessTokenURL != "" {
|
if providerData.BackendRevokeAccessTokenURL != "" {
|
||||||
err := PicsRevokeAccessToken(providerData.BackendRevokeAccessTokenURL, session.AccessToken, providerData.ClientID, providerData.ClientSecret)
|
err := PicsRevokeAccessToken(providerData.BackendRevokeAccessTokenURL, session.AccessToken, providerData.ClientID, providerData.ClientSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("error while calling backend revoke access token: %v", err)
|
logger.Errorf("error while calling backend revoke access token: %v", err)
|
||||||
} else {
|
} else {
|
||||||
p.picsAuditClient.CreateSuccessfulRevokeAccessTokenAuditEntry(session, req.RequestURI, req.Header.Get("edisp-org-id"))
|
p.picsAuditClient.CreateSuccessfulRevokeAccessTokenAuditEntry(session, req.RequestURI, req.Header.Get("edisp-org-id"), req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1010,7 +1010,7 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
|
||||||
p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
|
p.ErrorPage(rw, req, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.picsAuditClient.CreateSuccessfulLoginAuditEntry(session, appRedirect, req.Header.Get("edisp-org-id"))
|
p.picsAuditClient.CreateSuccessfulLoginAuditEntry(session, appRedirect, req.Header.Get("edisp-org-id"), req)
|
||||||
http.Redirect(rw, req, appRedirect, http.StatusFound)
|
http.Redirect(rw, req, appRedirect, http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: unauthorized")
|
logger.PrintAuthf(session.Email, req, logger.AuthFailure, "Invalid authentication via OAuth2: unauthorized")
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -52,34 +55,60 @@ func NewAuditClient(opts *ClientOpts) (*Client, error) {
|
||||||
return &Client{enabled: opts.Enabled, apiSignature: apiSignature, client: client, opts: opts}, nil
|
return &Client{enabled: opts.Enabled, apiSignature: apiSignature, client: client, opts: opts}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateSuccessfulLoginAuditEntry(ss *sessions.SessionState, appURL string, tenantID string) {
|
func (c *Client) CreateSuccessfulLoginAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, req *http.Request) {
|
||||||
coding := Coding{
|
coding := Coding{
|
||||||
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110114", Display: "User Authentication"}
|
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110114", Display: "User Authentication"}
|
||||||
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding)
|
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateFailedLoginAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, errorDesc string) {
|
func (c *Client) CreateFailedLoginAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, errorDesc string, req *http.Request) {
|
||||||
coding := Coding{
|
coding := Coding{
|
||||||
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110114", Display: "User Authentication"}
|
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110114", Display: "User Authentication"}
|
||||||
c.createAuditEntry(ss, appURL, tenantID, "1", errorDesc, &coding)
|
c.createAuditEntry(ss, appURL, tenantID, "1", errorDesc, &coding, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateSuccessfulLogoutAuditEntry(ss *sessions.SessionState, appURL string, tenantID string) {
|
func (c *Client) CreateSuccessfulLogoutAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, req *http.Request) {
|
||||||
coding := Coding{
|
coding := Coding{
|
||||||
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110123", Display: "User Logout All Sessions"}
|
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110123", Display: "User Logout All Sessions"}
|
||||||
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding)
|
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CreateSuccessfulRevokeAccessTokenAuditEntry(ss *sessions.SessionState, appURL string, tenantID string) {
|
func (c *Client) CreateSuccessfulRevokeAccessTokenAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, req *http.Request) {
|
||||||
coding := Coding{
|
coding := Coding{
|
||||||
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110123", Display: "User revoked access token"}
|
System: "http://hl7.org/fhir/ValueSet/audit-event-type", Version: "1", Code: "110123", Display: "User revoked access token"}
|
||||||
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding)
|
c.createAuditEntry(ss, appURL, tenantID, "0", "Success", &coding, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) createAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, outcomeCode string, outcomeDesc string, coding *Coding) {
|
func (c *Client) createAuditEntry(ss *sessions.SessionState, appURL string, tenantID string, outcomeCode string, outcomeDesc string, coding *Coding, req *http.Request) {
|
||||||
if !c.enabled {
|
if !c.enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Service/component identifier
|
||||||
|
serviceIDs := []string{"oauth2proxy"}
|
||||||
|
var targetIP string
|
||||||
|
if hn, err := os.Hostname(); err == nil {
|
||||||
|
serviceIDs = append(serviceIDs, hn)
|
||||||
|
addrs, err := net.LookupHost(hn)
|
||||||
|
if err == nil && len(addrs) > 0 {
|
||||||
|
targetIP = addrs[0]
|
||||||
|
} else {
|
||||||
|
targetIP = hn
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetIP = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract source IP address
|
||||||
|
sourceIP := ""
|
||||||
|
if req != nil {
|
||||||
|
sourceIP = req.RemoteAddr
|
||||||
|
if xff := req.Header.Get("X-Forwarded-For"); xff != "" {
|
||||||
|
ips := strings.Split(xff, ",")
|
||||||
|
sourceIP = strings.TrimSpace(ips[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auditObject := RootEvent{
|
auditObject := RootEvent{
|
||||||
ResourceType: "AuditEvent",
|
ResourceType: "AuditEvent",
|
||||||
Event: &Event{
|
Event: &Event{
|
||||||
|
|
@ -88,7 +117,6 @@ func (c *Client) createAuditEntry(ss *sessions.SessionState, appURL string, tena
|
||||||
DateTime: time.Now().UTC().Format(time.RFC3339),
|
DateTime: time.Now().UTC().Format(time.RFC3339),
|
||||||
Outcome: outcomeCode,
|
Outcome: outcomeCode,
|
||||||
OutcomeDesc: outcomeDesc},
|
OutcomeDesc: outcomeDesc},
|
||||||
|
|
||||||
Participant: []*Participant{
|
Participant: []*Participant{
|
||||||
{AltID: ss.User, UserID: UserID{Value: ss.Email}, Name: ss.PreferredUsername, Requestor: true}},
|
{AltID: ss.User, UserID: UserID{Value: ss.Email}, Name: ss.PreferredUsername, Requestor: true}},
|
||||||
Source: Source{
|
Source: Source{
|
||||||
|
|
@ -133,6 +161,9 @@ func (c *Client) createAuditEntry(ss *sessions.SessionState, appURL string, tena
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ServiceIDs: serviceIDs,
|
||||||
|
SourceIPAddress: sourceIP,
|
||||||
|
TargetIPAddress: targetIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
auditMessage, err := json.Marshal(auditObject)
|
auditMessage, err := json.Marshal(auditObject)
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,12 @@ type Event struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RootEvent struct {
|
type RootEvent struct {
|
||||||
ResourceType string `json:"resourceType,omitempty"`
|
ResourceType string `json:"resourceType,omitempty"`
|
||||||
Event *Event `json:"event,omitempty"`
|
Event *Event `json:"event,omitempty"`
|
||||||
Participant []*Participant `json:"participant,omitempty"`
|
Participant []*Participant `json:"participant,omitempty"`
|
||||||
Source Source `json:"source,omitempty"`
|
Source Source `json:"source,omitempty"`
|
||||||
Object []*Object `json:"object,omitempty"`
|
Object []*Object `json:"object,omitempty"`
|
||||||
|
ServiceIDs []string `json:"service_ids,omitempty"`
|
||||||
|
SourceIPAddress string `json:"source_ip_address,omitempty"`
|
||||||
|
TargetIPAddress string `json:"target_ip_address,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue