Change:
We don't currently have any test coverage of impersonation for audit logging. I think the audit e2e test () would be a good place to do so. /area audit /area test /sig auth /help /good-first-issue
This request has been marked as suitable for new contributors. Please ensure the request meets the requirements listed . If this request no longer meets these requirements, the label can be removed by commenting with the command. <detailsIn response to : We don't currently have any test coverage of impersonation for audit logging. I think the audit e2e test () would be a good place to do so. /area test /sig auth /help /good-first-issue Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
assign I would like to work on this issue. Please give me some tips and instructions which i should take into consideration and will help me accomplishing this task successfully.
Take a look at the existing audit tests (linked in description), and the documentation on . I recommended doing a manual test first, so you understand how it works. The audit test actually already uses impersonation (), so you can just do something similar and then verify that it is logged correctly (the field).
Also, if you need help with the e2e framework, is the place to start.
Ok, thank you :)
GitHub didn't allow me to assign the following users: loqutus. Note that only and repo collaborators can be assigned. For more information please see <detailsIn response to : /assign Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
How is it going? Do you need some help?
Just watch around.
I am pretty confused regarding how to write test cases
Can you give me more details about what it is you are struggling with? Writing test cases in general? I'm also new to the project but perhaps I can help you out. :)
Yes, I am struggling with writing test cases in general
Are you still struggling with test cases in general? Please tell me if I am wrong, but I think here a test case is just testing that a particular call to the api logs specific information (represented by the struct AuditEvent). If I am correct, we don't need to create a complete new test case, but rather edit the exiting ones by checking one more info. Additionally, I am not sure that we can test this locally with kubetest, since the test seems to only accept the gce provider (google cloud engine). Hope this helps.
yes, I am struggling for writing test case as well as this was in my concious as well that how I am gonna test this test case
OK, I think I got what the issue is about. Please let me know if you are still struggling and prefer to hand it over. I'd like to give it a shot but don't want to steal the opportunity to make a first contribution to the project from you.
yaa sure you can give it a shot
FYI I'm working on this issue. I'm trying to get audit logging activated in minikube so I can manually test impersonation and see the log output (in order to see what the test has to cover). However, trying to get it activated in minikube is more difficult than I thought. :grimacing:
Hey how is it going with the manual test? The only way I found with minikube, is to start it with the following command (I use minikube v0.30.0). This activates audit logs, and configures the logs file path in the minikube's VM. Then you could use an api call using kubectl, with and without impersonation, and see the difference in logs. Notice that it does not matter if we have not created any pods at this point, because we just want to test the audit. To look into the logs you need to ssh into Minikube and look into a particular file. The manual test is a good thing to see how it works. But you don't actually need to code the whole thing, I think. as the current audit test already loads and parses the log file (see inside CheckAuditLines, and then parseAuditLine).
Hey , thanks for your extensive anser. I managed to get in tested manually with minikube a couple of days ago, though it was not possible for me to get an costum audit policy file loaded even though it was available (somehow the extra config flag was ignored). Anyway, I spent the last couple of days figuring out how to best run the e2e tests on my macbook (I'm using Vagrant right now since there were some problems with running the tests in docker on mac). As you already mentioned in a previous comment, the audit tests only accept gce as a provider. I tried to simply comment that line out in order to see what happens if it runs on my local machine, but (unsuprisingly) it blew up. So the current status is, that I'm now trying to write the test case for impersonation relying on the CI to see if it runs through (since I cannot run the test locally) which is not ideal but I don't have a better idea atm.

Discussion:
anonymousClient, err := clientset.NewForConfig(config) framework.ExpectNoError(err) <ins> By("Creating a kubernetes client that impersonates an authorized user") config, err = framework.LoadConfig() framework.ExpectNoError(err) config.Impersonate = restclient.ImpersonationConfig{ UserName: "superman", Groups:   []string{"system:masters"}, } impersonatedClient, err := clientset.NewForConfig(config) framework.ExpectNoError(err) </ins> testCases := []struct { action func() events []utils.AuditEvent

}, }, }, <ins> // List pods as impersonated user. { func() { _, err = impersonatedClient.CoreV1().Pods(namespace).List(metav1.ListOptions{}) framework.ExpectNoError(err, "failed to list pods") }, []utils.AuditEvent{ { Level:              auditinternal.LevelRequest, Stage:              auditinternal.StageResponseComplete, RequestURI:         fmt.Sprintf("/api/v1/namespaces/%s/pods", namespace), Verb:               "list", Code:               200, User:               auditTestUser, ImpersonatedUser:   "superman", ImpersonatedGroups: "system:masters", Resource:           "pods", Namespace:          namespace, RequestObject:      false, ResponseObject:     false, AuthorizeDecision:  "allow", }, }, }, </ins> } // test authorizer annotations, RBAC is required.

}, []utils.AuditEvent{ { <del> Level:             auditinternal.LevelRequest, Stage:             auditinternal.StageResponseComplete, RequestURI:        fmt.Sprintf("/api/v1/namespaces/%s/pods/another-audit-pod", namespace), Verb:              "get", Code:              403, User:              auditTestUser, Resource:          "pods", Namespace:         namespace, RequestObject:     false, ResponseObject:    false, AuthorizeDecision: "forbid", </del> <ins> Level:              auditinternal.LevelRequest, Stage:              auditinternal.StageResponseComplete, RequestURI:         fmt.Sprintf("/api/v1/namespaces/%s/pods/another-audit-pod", namespace), Verb:               "get", Code:               403, User:               auditTestUser, ImpersonatedUser:   "system:anonymous", ImpersonatedGroups: "system:unauthenticated", Resource:           "pods", Namespace:          namespace, RequestObject:      false, ResponseObject:     false, AuthorizeDecision:  "forbid", </ins> }, }, },

"bufio" "fmt" "io" <ins> "sort" "strings" </ins> "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema"

) type AuditEvent struct { <del> Level             auditinternal.Level Stage             auditinternal.Stage RequestURI        string Verb              string Code              int32 User              string Resource          string Namespace         string RequestObject     bool ResponseObject    bool AuthorizeDecision string </del> <ins> Level              auditinternal.Level Stage              auditinternal.Stage RequestURI         string Verb               string Code               int32 User               string ImpersonatedUser   string ImpersonatedGroups string Resource           string Namespace          string RequestObject      bool ResponseObject     bool AuthorizeDecision  string </ins> } // Search the audit log for the expected audit lines.

if e.RequestObject != nil { event.RequestObject = true } <ins> if e.ImpersonatedUser != nil { event.ImpersonatedUser = e.ImpersonatedUser.Username sort.Strings(e.ImpersonatedUser.Groups) event.ImpersonatedGroups = strings.Join(e.ImpersonatedUser.Groups, ",") } </ins> event.AuthorizeDecision = e.Annotations["authorization.k8s.io/decision"] return event, nil }