Repository: Azure/aad-pod-identity
Pull request #343 (2019-08-14 18:51:01)

Redact client id in NMI logs
<!-- Thank you for helping AAD Pod Identity with a pull request! -->

**Reason for Change**:
<!-- What does this PR improve or fix in AAD Pod Identity? Why is it needed? -->
Redact client id in NMI logs

**Issue Fixed**:
<!-- If this PR fixes GitHub issue 1234, add "Fixes #1234" to the next line. -->

**Notes for Reviewers**:



Patch:
diff --git a/pkg/nmi/server/server.go b/pkg/nmi/server/server.go
index 6cf29022..9e206943 100644
--- a/pkg/nmi/server/server.go
+++ b/pkg/nmi/server/server.go
@@ -363,15 +363,16 @@ func getTokenForMatchingID(kubeClient k8s.Client, logger *log.Entry, rqClientID
 			logger.Warningf("clientid mismatch, requested:%s available:%s", rqClientID, clientID)
 			continue
 		}
+
 		idType := v.Spec.Type
 		switch idType {
 		case aadpodid.UserAssignedMSI:
-			logger.Infof("matched identityType:%v clientid:%s resource:%s", idType, clientID, rqResource)
+			logger.Infof("matched identityType:%v clientid:%s resource:%s", idType, redactClientID(clientID), rqResource)
 			token, err := auth.GetServicePrincipalTokenFromMSIWithUserAssignedID(clientID, rqResource)
 			return token, clientID, err
 		case aadpodid.ServicePrincipal:
 			tenantid := v.Spec.TenantID
-			logger.Infof("matched identityType:%v tenantid:%s clientid:%s resource:%s", idType, tenantid, clientID, rqResource)
+			logger.Infof("matched identityType:%v tenantid:%s clientid:%s resource:%s", idType, tenantid, redactClientID(clientID), rqResource)
 			secret, err := kubeClient.GetSecret(&v.Spec.ClientPassword)
 			if err != nil {
 				return nil, clientID, err
diff --git a/pkg/nmi/server/utils.go b/pkg/nmi/server/utils.go
index f61fed5c..2242b0e8 100644
--- a/pkg/nmi/server/utils.go
+++ b/pkg/nmi/server/utils.go
@@ -1,6 +1,10 @@
 package server
 
-import log "github.com/sirupsen/logrus"
+import (
+	"regexp"
+
+	log "github.com/sirupsen/logrus"
+)
 
 // Log - this struct abstracts the logging libraries into single interface.
 type Log struct {
@@ -15,3 +19,12 @@ func (l Log) Info(msg string) {
 func (l Log) Errorf(format string, args ...interface{}) {
 	log.Errorf(format, &args)
 }
+
+func redactClientID(clientID string) string {
+	return redact(clientID, "$1##### REDACTED #####$3")
+}
+
+func redact(src, repl string) string {
+	r, _ := regexp.Compile("^(\\S{4})(\\S|\\s)*(\\S{4})$")
+	return r.ReplaceAllString(src, repl)
+}


Test patch:
diff --git a/pkg/nmi/server/server_test.go b/pkg/nmi/server/server_test.go
index f836ab27..a443486c 100644
--- a/pkg/nmi/server/server_test.go
+++ b/pkg/nmi/server/server_test.go
@@ -31,7 +31,7 @@ func TestGetTokenForMatchingIDBySP(t *testing.T) {
 		Spec: aadpodid.AzureIdentitySpec{
 			Type:           aadpodid.ServicePrincipal,
 			TenantID:       "tid",
-			ClientID:       "cid",
+			ClientID:       "aabc0000-a83v-9h4m-000j-2c0a66b0c1f9",
 			ClientPassword: secretRef,
 		},
 	}
diff --git a/pkg/nmi/server/utils_test.go b/pkg/nmi/server/utils_test.go
new file mode 100644
index 00000000..151d4d0b
--- /dev/null
+++ b/pkg/nmi/server/utils_test.go
@@ -0,0 +1,26 @@
+package server
+
+import (
+	"testing"
+)
+
+func TestRedactClientID(t *testing.T) {
+	tests := []struct {
+		name     string
+		clientID string
+		expected string
+	}{
+		{
+			name:     "should redact client id",
+			clientID: "aabc0000-a83v-9h4m-000j-2c0a66b0c1f9",
+			expected: "aabc##### REDACTED #####c1f9",
+		},
+	}
+
+	for _, test := range tests {
+		actual := redactClientID(test.clientID)
+		if actual != test.expected {
+			t.Fatalf("expected: %s, got %s", test.expected, actual)
+		}
+	}
+}