k8s.io/apiserver@v0.31.1/pkg/endpoints/filters/authn_audit_test.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package filters
    18  
    19  import (
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"strings"
    25  	"testing"
    26  
    27  	auditinternal "k8s.io/apiserver/pkg/apis/audit"
    28  	"k8s.io/apiserver/pkg/audit/policy"
    29  )
    30  
    31  func TestFailedAuthnAudit(t *testing.T) {
    32  	sink := &fakeAuditSink{}
    33  	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil)
    34  	handler := WithFailedAuthenticationAudit(
    35  		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    36  			http.Error(w, "", http.StatusUnauthorized)
    37  		}),
    38  		sink, fakeRuleEvaluator)
    39  	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
    40  	req.RemoteAddr = "127.0.0.1"
    41  	req = withTestContext(req, nil, nil)
    42  	req.SetBasicAuth("username", "password")
    43  	handler.ServeHTTP(httptest.NewRecorder(), req)
    44  
    45  	if len(sink.events) != 1 {
    46  		t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events))
    47  	}
    48  	ev := sink.events[0]
    49  	if ev.ResponseStatus.Code != http.StatusUnauthorized {
    50  		t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code)
    51  	}
    52  	if !strings.Contains(ev.ResponseStatus.Message, "basic") {
    53  		t.Errorf("Expected response status message to contain basic auth method, got %s", ev.ResponseStatus.Message)
    54  	}
    55  	if ev.Verb != "list" {
    56  		t.Errorf("Unexpected verb, expected list, got %s", ev.Verb)
    57  	}
    58  	if ev.RequestURI != "/api/v1/namespaces/default/pods" {
    59  		t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI)
    60  	}
    61  }
    62  
    63  func TestFailedMultipleAuthnAudit(t *testing.T) {
    64  	sink := &fakeAuditSink{}
    65  	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil)
    66  	handler := WithFailedAuthenticationAudit(
    67  		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    68  			http.Error(w, "", http.StatusUnauthorized)
    69  		}),
    70  		sink, fakeRuleEvaluator)
    71  	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
    72  	req.RemoteAddr = "127.0.0.1"
    73  	req = withTestContext(req, nil, nil)
    74  	req.SetBasicAuth("username", "password")
    75  	req.TLS = &tls.ConnectionState{PeerCertificates: []*x509.Certificate{{}}}
    76  	handler.ServeHTTP(httptest.NewRecorder(), req)
    77  
    78  	if len(sink.events) != 1 {
    79  		t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events))
    80  	}
    81  	ev := sink.events[0]
    82  	if ev.ResponseStatus.Code != http.StatusUnauthorized {
    83  		t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code)
    84  	}
    85  	if !strings.Contains(ev.ResponseStatus.Message, "basic") || !strings.Contains(ev.ResponseStatus.Message, "x509") {
    86  		t.Errorf("Expected response status message to contain basic and x509 auth method, got %s", ev.ResponseStatus.Message)
    87  	}
    88  	if ev.Verb != "list" {
    89  		t.Errorf("Unexpected verb, expected list, got %s", ev.Verb)
    90  	}
    91  	if ev.RequestURI != "/api/v1/namespaces/default/pods" {
    92  		t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI)
    93  	}
    94  }
    95  
    96  func TestFailedAuthnAuditWithoutAuthorization(t *testing.T) {
    97  	sink := &fakeAuditSink{}
    98  	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, nil)
    99  	handler := WithFailedAuthenticationAudit(
   100  		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   101  			http.Error(w, "", http.StatusUnauthorized)
   102  		}),
   103  		sink, fakeRuleEvaluator)
   104  	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
   105  	req.RemoteAddr = "127.0.0.1"
   106  	req = withTestContext(req, nil, nil)
   107  	handler.ServeHTTP(httptest.NewRecorder(), req)
   108  
   109  	if len(sink.events) != 1 {
   110  		t.Fatalf("Unexpected number of audit events generated, expected 1, got: %d", len(sink.events))
   111  	}
   112  	ev := sink.events[0]
   113  	if ev.ResponseStatus.Code != http.StatusUnauthorized {
   114  		t.Errorf("Unexpected response code, expected unauthorized, got %d", ev.ResponseStatus.Code)
   115  	}
   116  	if !strings.Contains(ev.ResponseStatus.Message, "no credentials provided") {
   117  		t.Errorf("Expected response status message to contain no credentials provided, got %s", ev.ResponseStatus.Message)
   118  	}
   119  	if ev.Verb != "list" {
   120  		t.Errorf("Unexpected verb, expected list, got %s", ev.Verb)
   121  	}
   122  	if ev.RequestURI != "/api/v1/namespaces/default/pods" {
   123  		t.Errorf("Unexpected user, expected /api/v1/namespaces/default/pods, got %s", ev.RequestURI)
   124  	}
   125  }
   126  
   127  func TestFailedAuthnAuditOmitted(t *testing.T) {
   128  	sink := &fakeAuditSink{}
   129  	fakeRuleEvaluator := policy.NewFakePolicyRuleEvaluator(auditinternal.LevelRequestResponse, []auditinternal.Stage{auditinternal.StageResponseStarted})
   130  	handler := WithFailedAuthenticationAudit(
   131  		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   132  			http.Error(w, "", http.StatusUnauthorized)
   133  		}),
   134  		sink, fakeRuleEvaluator)
   135  	req, _ := http.NewRequest("GET", "/api/v1/namespaces/default/pods", nil)
   136  	req.RemoteAddr = "127.0.0.1"
   137  	req = withTestContext(req, nil, nil)
   138  	handler.ServeHTTP(httptest.NewRecorder(), req)
   139  
   140  	if len(sink.events) != 0 {
   141  		t.Fatalf("Unexpected number of audit events generated, expected 0, got: %d", len(sink.events))
   142  	}
   143  }