@@ -469,3 +469,144 @@ func TestRealImplantSecureKeyExchangeE2E(t *testing.T) {
469469
470470 t .Log ("secure key exchange E2E test passed: cold start → key exchange → encrypted commands" )
471471}
472+
473+ // TestRealImplantTLSPipelineE2E verifies the implant can connect to a TLS-enabled
474+ // pipeline (self-signed cert with CA verification) and execute commands normally.
475+ // This tests the full certificate chain: pipeline generates CA+cert → profile
476+ // passes CA to implant → implant verifies server cert → encrypted session works.
477+ func TestRealImplantTLSPipelineE2E (t * testing.T ) {
478+ testsupport .RequireRealImplantEnv (t )
479+
480+ h := testsupport .NewControlPlaneHarness (t )
481+ listenerName := fmt .Sprintf ("real-tls-listener-%d" , time .Now ().UnixNano ())
482+ pipelineName := fmt .Sprintf ("real-tls-pipe-%d" , time .Now ().UnixNano ())
483+
484+ // Create a TLS-enabled TCP pipeline (self-signed CA + server cert)
485+ pipeline := testsupport .NewRealTLSTCPPipeline (t , listenerName , pipelineName )
486+ implant := testsupport .NewRealImplant (t , h , pipeline )
487+ if err := implant .Start (t ); err != nil {
488+ t .Fatalf ("real TLS implant start failed: %v" , err )
489+ }
490+
491+ waitRealActiveConnection (t , implant .SessionID )
492+ waitRealPostRegisterCheckin (t , implant .SessionID )
493+
494+ runtimeSession := mustRealRuntimeSession (t , implant .SessionID )
495+ if runtimeSession .WorkDir == "" {
496+ t .Fatal ("registered TLS session should include a non-empty workdir" )
497+ }
498+
499+ // Connect as admin client
500+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
501+ defer cancel ()
502+ conn , err := h .Connect (ctx )
503+ if err != nil {
504+ t .Fatalf ("Connect failed: %v" , err )
505+ }
506+ t .Cleanup (func () { _ = conn .Close () })
507+
508+ rpc := clientrpc .NewMaliceRPCClient (conn )
509+ sessionCtx := metadata .NewOutgoingContext (context .Background (), metadata .Pairs (
510+ "session_id" , implant .SessionID ,
511+ "callee" , consts .CalleeCMD ,
512+ ))
513+
514+ // Enable keepalive
515+ enableRealKeepalive (t , & realRPCFixture {
516+ h : h , implant : implant , rpc : rpc , session : sessionCtx ,
517+ }, true )
518+
519+ waitRealActiveConnection (t , implant .SessionID )
520+
521+ // Execute pwd over TLS
522+ pwdTask , err := rpc .Pwd (sessionCtx , & implantpb.Request {Name : consts .ModulePwd })
523+ if err != nil {
524+ t .Fatalf ("Pwd (over TLS) failed: %v" , err )
525+ }
526+ pwdContent := waitRealTaskFinish (t , rpc , implant .SessionID , pwdTask .TaskId )
527+ pwdOutput := strings .TrimSpace (pwdContent .GetSpite ().GetResponse ().GetOutput ())
528+ if pwdOutput == "" {
529+ t .Fatal ("pwd output over TLS should not be empty" )
530+ }
531+ t .Logf ("pwd over TLS: %s" , pwdOutput )
532+
533+ // Verify workdir matches
534+ runtimeSession = mustRealRuntimeSession (t , implant .SessionID )
535+ if normalizeWindowsPath (pwdOutput ) != normalizeWindowsPath (runtimeSession .WorkDir ) {
536+ t .Fatalf ("pwd = %q, want workdir %q" , pwdOutput , runtimeSession .WorkDir )
537+ }
538+
539+ // Disable keepalive
540+ enableRealKeepalive (t , & realRPCFixture {
541+ h : h , implant : implant , rpc : rpc , session : sessionCtx ,
542+ }, false )
543+
544+ t .Log ("TLS pipeline E2E test passed: self-signed CA → TLS handshake → encrypted commands" )
545+ }
546+
547+ // TestRealImplantMTLSPipelineE2E verifies mutual TLS: both server and implant
548+ // present certificates signed by the same CA. The server verifies the implant's
549+ // client certificate, and the implant verifies the server's certificate.
550+ //
551+ func TestRealImplantMTLSPipelineE2E (t * testing.T ) {
552+ testsupport .RequireRealImplantEnv (t )
553+
554+ h := testsupport .NewControlPlaneHarness (t )
555+ listenerName := fmt .Sprintf ("real-mtls-listener-%d" , time .Now ().UnixNano ())
556+ pipelineName := fmt .Sprintf ("real-mtls-pipe-%d" , time .Now ().UnixNano ())
557+
558+ // Create mTLS pipeline (CA + server cert + client cert)
559+ pipeline , mtlsCerts := testsupport .NewRealMTLSTCPPipeline (t , listenerName , pipelineName )
560+ implant := testsupport .NewRealImplant (t , h , pipeline )
561+ implant .MTLSCerts = mtlsCerts // inject client certs into profile
562+ if err := implant .Start (t ); err != nil {
563+ t .Fatalf ("real mTLS implant start failed: %v" , err )
564+ }
565+
566+ waitRealActiveConnection (t , implant .SessionID )
567+ waitRealPostRegisterCheckin (t , implant .SessionID )
568+
569+ runtimeSession := mustRealRuntimeSession (t , implant .SessionID )
570+ if runtimeSession .WorkDir == "" {
571+ t .Fatal ("registered mTLS session should include a non-empty workdir" )
572+ }
573+
574+ // Connect as admin client
575+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
576+ defer cancel ()
577+ conn , err := h .Connect (ctx )
578+ if err != nil {
579+ t .Fatalf ("Connect failed: %v" , err )
580+ }
581+ t .Cleanup (func () { _ = conn .Close () })
582+
583+ rpc := clientrpc .NewMaliceRPCClient (conn )
584+ sessionCtx := metadata .NewOutgoingContext (context .Background (), metadata .Pairs (
585+ "session_id" , implant .SessionID ,
586+ "callee" , consts .CalleeCMD ,
587+ ))
588+
589+ enableRealKeepalive (t , & realRPCFixture {
590+ h : h , implant : implant , rpc : rpc , session : sessionCtx ,
591+ }, true )
592+
593+ waitRealActiveConnection (t , implant .SessionID )
594+
595+ // Execute pwd over mTLS channel
596+ pwdTask , err := rpc .Pwd (sessionCtx , & implantpb.Request {Name : consts .ModulePwd })
597+ if err != nil {
598+ t .Fatalf ("Pwd (over mTLS) failed: %v" , err )
599+ }
600+ pwdContent := waitRealTaskFinish (t , rpc , implant .SessionID , pwdTask .TaskId )
601+ pwdOutput := strings .TrimSpace (pwdContent .GetSpite ().GetResponse ().GetOutput ())
602+ if pwdOutput == "" {
603+ t .Fatal ("pwd output over mTLS should not be empty" )
604+ }
605+ t .Logf ("pwd over mTLS: %s" , pwdOutput )
606+
607+ enableRealKeepalive (t , & realRPCFixture {
608+ h : h , implant : implant , rpc : rpc , session : sessionCtx ,
609+ }, false )
610+
611+ t .Log ("mTLS pipeline E2E test passed: mutual certificate verification → encrypted commands" )
612+ }
0 commit comments